volatile概念

volatile 是易变的、不稳定的意思。

volatile关键字和const 一样是一种类型修饰符,用它修饰的变量表示可以被某些编译器未知的因素更改,比如操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。

先看看下面的例子:
int i=10;
int j = i;//(1)语句
int k = i;//(2)语句
这时候编译器对代码进行优化,因为在(1)、(2)两条语句中,i 没有被用作左值。这时候编译器认为i 的值没有发生改变,所以在(1)语句时从内存中取出i 的值赋给j 之后,这个值并没有被丢掉,而是在(2)语句时继续用这个值给k 赋值。编译器不会生成出汇编代码重新从内存里取i 的值,这样提高了效率。但要注意:(1)、(2)语句之间i 没有被用作左值才行。
再看另一个例子:
volatile int i=10;
int j = i;//(3)语句
int k = i;//(4)语句
volatile 关键字告诉编译器i 是随时可能发生变化的,每次使用它的时候必须从内存中取出i的值,因而编译器生成的汇编代码会重新从i 的地址处读取数据放在k 中。

这样看来,如果i 是一个寄存器变量或者表示一个端口数据或者是多个线程的共享数据,就容易出错,所以说volatile 可以保证对特殊地址的稳定访问。

一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子: 
    1). 并行设备的硬件寄存器(如:状态寄存器) 
    2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables) 
    3). 多线程应用中被几个任务共享的变量 
    回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所用这些都要求volatile变量。不懂得volatile内容将会带来灾难。

volatile问题

假设被面试者正确地回答了这几个问题(嗯,怀疑这是否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。
1). 一个参数既可以是const还可以是volatile吗?解释为什么。
2). 一个指针可以是volatile 吗?解释为什么。
3). 下面的函数有什么错误:
int square(volatile int *ptr)
{
return *ptr * *ptr;
}
下面是答案:
1). 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
2). 是的。尽管这并不很常见。一个例子是当一个中断服务子程序修该一个指向一个buffer的指针时。
3). 这段代码的有个恶作剧。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}
由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:
long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}

总结

1. 编译器的优化(请高手帮我看看下面的理解)

  • 在本次线程内, 当读取一个变量时,为提高存取速度,编译器优化时有时会先把变量读取到一个寄存器中;以后,再取变量值时,就直接从寄存器中取值;
  • 当变量值在本线程里改变时,会同时把变量的新值copy到该寄存器中,以便保持一致
  • 当变量在因别的线程等而改变了值,该寄存器的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致
  • 当该寄存器在因别的线程等而改变了值,原变量的值不会改变,从而造成应用程序读取的值和实际的变量值不一致

2. 
在什么情况下会出现

  • 并行设备的硬件寄存器(如:状态寄存器)
  • 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
  • 多线程应用中被几个任务共享的变量

补充: 
volatile
应该解释为

直接存取原始内存地址

比较合适,

易变的

这种解释简直有点误导人;

[C++基础]关键词volatile的更多相关文章

  1. robotframework - 基础关键词

    robotframework基础关键词如下: 1.可在python.notepad++ 编辑: *** Settings *** *** Test Cases ***variable ${a} Set ...

  2. C# 基础回顾: volatile 关键字

    有些人可能从来没看到过这个关键字,这也难怪,因为这个关键字并不常用.那这个关键字到底有什么用呢? 我在网上搜索这个关键字的时候,发现很多朋友都有一个错误的认识 ------ 认为这个关键字可以防止并发 ...

  3. Java并发编程基础之volatile

    首先简单介绍一下volatile的应用,volatile作为Java多线程中轻量级的同步措施,保证了多线程环境中“共享变量”的可见性.这里的可见性简单而言可以理解为当一个线程修改了一个共享变量的时候, ...

  4. java基础系列--volatile关键字

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/7833881.html 1.volatile简述 据说,volatile是java语言中最轻 ...

  5. 并发编程基础之volatile关键字的用法

    一:概念 volatile关键字是一个轻量级的线程同步,它可以保证线程之间对于共享变量的同步,假设有两个线程a和b, 它们都可以访问一个成员变量,当a修改成员变量的值的时候,要保证b也能够取得成员变量 ...

  6. java基础-关键词super与this

    转发:itbooks this是调用自己本身的构造函数,而super是调用父类中的构造函数. 这两个关键词是用在构造函数中的,这两个关键词的设计也是对封装特性的一种考虑,避免编写不必要的重复代码. c ...

  7. python基础关键词触发的魔法方法

    with: __enter__ __exit__ dic={} 获取容器中指定元素的行为 dic["name"] = "egon" #设置值 __setitem ...

  8. Java基础之Volatile原理

    原文链接: http://www.aoaoyi.com/archives/956.html 计算机在执行程序时,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据 的读取和写入.由于程序运 ...

  9. Java基础教程:多线程杂谈——Volatile

    Java基础教程:多线程杂谈——Volatile 引入Volatile Java语言提供了一种稍弱的同步机制,即Volatile变量,用来确保将变量的更新操作通知到其他线程.当把变量声明为Volati ...

随机推荐

  1. C# 中的委托和事件 转张子阳

    引言 委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去 ...

  2. 4071: [Apio2015]巴邻旁之桥

    Description 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B. 每一块区域沿着河岸都建了恰好 1000000001 栋的建筑,每条岸边的建筑都从 0 编号到 10000 ...

  3. C++ 类族的设计

     - 类族的设计]    按以下的提示,由基类的设计和测试开始,逐渐地完成各个类的设计,求出圆格柱体的表面积.体积并输出并且完成要求的计算任务:    (1)先建立一个Point(点)类,包含数据成员 ...

  4. Java多线程初学者指南(11):使用Synchronized块同步方法

    synchronized关键字有两种用法.第一种就是在<使用Synchronized关键字同步类方法>一文中所介绍的直接用在方法的定义中.另外一种就是synchronized块.我们不仅可 ...

  5. Linq学习之旅——LINQ查询表达式

    1. 概述 2. from子句 3. where子句 4. select子句 5. group子句 6. into子句 7. 排序子句 8. let子句 9. join子句 10. 小结 1. 概述 ...

  6. webkit javascript

    http://www.infoq.com/cn/news/2013/02/douglas-interview http://blog.csdn.net/horkychen/article/detail ...

  7. Ubuntu 14.04安装Chromium浏览器并添加Flash插件Pepper Flas

    转自Ubuntu 14.04安装Chromium浏览器并添加Flash插件Pepper Flash Player Chromium谷歌的开源浏览器将不再支持Netscape浏览器插件API,Adobe ...

  8. ScrollView中嵌套两个ListView

    做的项目中要使用两个ListView在同一个页面上下显示,因为数据源不同,不能通过在Adapter中设置标志位去区分显示,最后只能硬着头皮做一个ScrollView嵌套两个ListView,但按正常情 ...

  9. 9.png(9位图)在android中作为background使用导致居中属性不起作用的解决方法

    在使用到9.png的布局上面添加 android:padding="0dip" 比如 <LinearLayout            android:layout_widt ...

  10. StorSimple 简介

     2014年 10月 28日,星期二 PRACHEETI NAGARKAR DESAI 混合云存储业务资深项目经理 在此我很荣幸地宣布StorSimple解决方案已经在中国正式上市.该方案为IT部 ...