`

关于volatile类型的变量

阅读更多
转自CSDN上面看到的一段话,个人感觉解释的比较透彻易懂,拿来学习一下:
http://topic.csdn.net/t/20060106/23/4502657.html

volatile仅仅一个不起眼的关键字  
尽管C和C++标准对于线程都明显的“保持沉默”,但它们以volatile关键字的形式,确实为多线程保留了一点特权。  

就象大家更熟悉的const一样,volatile是一个类型修饰符(type   modifier)。它是被设计用来修饰被不同线程访问和修改的变量。如果没有volatile,基本上会导致这样的结果:要么无法编写多线程程序,要么编译器失去大量优化的机会。下面我们来一个个说明。  

考虑下面的代码:  

class   Gadget  
{  
public:  
void   Wait()  
{  
while   (!flag_)  
{  
Sleep(1000);   //   sleeps   for   1000   milliseconds  
}  
}  
void   Wakeup()  
{  
flag_   =   true;  
}  
...  
private:  
bool   flag_;  
};  

上面代码中Gadget::Wait的目的是每过一秒钟去检查一下flag_成员变量,当flag_被另一个线程设为true时,该函数才会返回。至少这是程序作者的意图,然而,这个Wait函数是错误的。  
假设编译器发现Sleep(1000)是调用一个外部的库函数,它不会改变成员变量flag_,那么编译器就可以断定它可以把flag_缓存在寄存器中,以后可以访问该寄存器来代替访问较慢的主板上的内存。这对于单线程代码来说是一个很好的优化,但是在现在这种情况下,它破坏了程序的正确性:当你调用了某个Gadget的Wait函数后,即使另一个线程调用了Wakeup,Wait还是会一直循环下去。这是因为flag_的改变没有反映到缓存它的寄存器中去。编译器的优化未免有点太……乐观了。  

在大多数情况下,把变量缓存在寄存器中是一个非常有价值的优化方法,如果不用的话很可惜。C和C++给你提供了显式禁用这种缓存优化的机会。如果你声明变量是使用了volatile修饰符,编译器就不会把这个变量缓存在寄存器里——每次访问都将去存取变量在内存中的实际位置。这样你要对Gadget的Wait/Wakeup做的修改就是给flag_加上正确的修饰:  

class   Gadget  
{  
public:  
...   as   above   ...  
private:  
volatile   bool   flag_;  
};  

大多数关于volatile的原理和用法的解释就到此为止,并且建议你用volatile修饰在多个线程中使用的原生类型变量。然而,你可以用volatile做更多的事,因为它是神奇的C++类型系统的一部分。  
把volatile用于自定义类型  
volatile修饰不仅可以用于原生类型,也可以用于自定义类型。这时候,volatile修饰方式类似于const(你也可以对一个类型同时使用const和volatile)。  

与const不同,volatile的作用对于原生类型和自定义类型是有区别的。就是说,原生类型有volatile修饰时,仍然支持它们的各种操作(加、乘、赋值等等),然而对于class来说,就不是这样。举例来说,你可以把一个非volatile的int的值赋给一个volatile的int,但是你不能把一个非volatile的对象赋给一个volatile对象。  
分享到:
评论

相关推荐

    volatile变量详解

    容易忽略的变量声明,但是很重要 volatile的作用: 作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值.

    java入门教程:数据类型_Java理论与实践如何正确使用Volatile变量.docx

    java入门教程:数据类型_Java理论与实践如何正确使用Volatile变量.docx

    关于volatile关键字的说明以及测试

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

    volatile使用详解

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

    JVM基础.doc

    如果不声明volatile,变量装载到本地变量 中,或者cpu cache中,多线程下很容易导 致状态不⼀一致。 • 声明了volatile,每次访问的都是主存中的数 据,⼀一致性能提升,但是还是不可靠的。 • volatile字段的访问...

    C语言中的volatile关键字

    volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改。  用volatile关键字声明的变量i每被访问时,执行部件都会从i相应的内存单元中取出i的值。  没有用volatile关键字声明...

    java多线程编程之慎重使用volatile关键字

    volatile关键字相信了解Java多线程的读者都很清楚它的作用。volatile关键字用于声明简单类型变量,下面看一下为什么要慎重使用volatile关键字

    volatile指针指来指去干嘛呀->nios2 PIO中断ISR

    Volatile是type-modifier,类型修饰符,限定一个对象可被外部进程(操作系统、硬件或并发进程等)改变,volatile与变量连用,可以让变量被不同的线程访问和修改。volatile就是告诉编译器,别对这个变量做任何优化,...

    C_gjz.rar_float

    break:跳出当前循环 else :条件语句否定分支(与 if 连用) switch :用于开关语句 case:开关语句分支 enum :声明枚举类型 register:声明积存器变量 typedef:用以给数据类型取别名 char :声明字符型变量或函数...

    EDA/PLD中的C语言中的volatile关键字

    volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改。  用volatile关键字声明的变量i每一次被访问时,执行部件都会从i相应的内存单元中取出i的值。  没有用volatile关键字...

    PIC单片机C知识点汇总

    PICC变量及定义 1、当变量为多字节数据时,PICC按低字节存放在低地址、高字节存放在高地址的原则存放变量,并以最低字节的地址作为该变量的地址。例如int型变量i的值为0X1234,...2、volatile(易变)型变量声明 volat

    Java并发学习-AtomicIntegerFieldUpdater字段原子更新类.docx

    字段必须是volatile类型的,在线程之间共享变量时保证立即可见 字段的描述类型( 修饰符public/protected/default/private )是与调用者与操作对象字段的关系一致。 也就是说调用者能够直接操作对象字段 ,...

    C++中volatile关键字的使用详解以及常见的误解

    volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统,硬件或者其他线程等

    C++大厂面试真题宝典 精选100道完结7章

    给大家整理了一些关于C++大厂面试2024最新真题,希望能够帮助到大家的面试: 1、synchronized 关键字和 volatile 关键字的区别 synchronized 关键字和 volatile 关键字是两个互补的存在,而不是对立的存在! ...

    STM32F4 AD采集DMA方式进行FFT计算

    这里面ADC_ConvertedValue是用volatile修饰的,用 volatile 声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。因为 ADC_ConvertedValue 这个变量值随时都是会被 DMA 控制器...

    STM32F4 AD-DMA-FFT计算.zip

    PS: 这里面ADC_ConvertedValue是用volatile修饰的,用 volatile 声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。因为 ADC_ConvertedValue 这个变量值随时都是会被 DMA 控制...

    c语言入门教程.txt

    由于数值的类型有多种,有整数、小数(浮点数)、字符等等,那么对应的变量就有整型变量、浮点型变量、字符型变量。变量还有其他的具体分类。整型变量还可具体分为无符号型、长整型和短整型。浮点型也可分为单精度型...

    C语言中auto,register,static,const,volatile的区别详细解析

    1)auto这个关键字用于声明变量的生存期为自动,即将不在任何类、结构、枚举、联合和函数中定义的变量视为全局...在一些含有较多的变量并且被经常调用的函数中,可以将一些数组声明为static类型,以减少建立或者初始化这

Global site tag (gtag.js) - Google Analytics