赞
踩
volatile的作用是: 作为指令关键字,确保本条指令不会因编译器的优化而省略,
且要求每次直接读值.
简单地说就是防止编译器对代码进行优化.比如如下程序:
XBYTE[2] = 0x55;
XBYTE[2] = 0x56;
XBYTE[2] = 0x57;
XBYTE[2] = 0x58;
对外部硬件而言,上述四条语句分别表示不同的操作,会产生四种不同的动作,
但是编译器却会对上述四条语句进行优化,认为只有XBYTE[2] = 0x58
(即忽略前三条语句,只产生一条机器代码)。如果键入volatile,则编译器会
逐一的进行编译并产生相应的机器代码(产生四条代码).
例子:
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。
下面是 volatile变量的几个例子:
1).并行设备的硬件寄存器(如:状态寄存器)
2).一个中断服务子程序中会访问到的非自动变量(Non - automatic variables)
3).多线程应用中被几个任务共享的变量
这是区分C程序员和嵌入式系统程序员的最基本的问题:嵌入式系统程序员经常同 硬件、中断、RTOS等等打交道,所有这些都要求使用volatile变量。不懂得volatile 内容将会带来灾难。
C/C++多线程编程中不要使用volatile。
(注:这里的意思指的是指望volatile解决多线程竞争问题是有很大风险的,除非所用的环境系统不可靠才会为了保险加上volatile,或者是从极限效率考虑来实现很底层的接口。这要求编写者对程序逻辑走向很清楚才行,不然就会出错)
C++11标准中明确指出解决多线程的数据竞争问题应该使用原子操作或者互斥锁。
C和C++中的volatile并不是用来解决多线程竞争问题的,而是用来修饰一些因为程序
不可控因素导致变化的变量,比如访问底层硬件设备的变量,以提醒编译器不要对该 变量的访问擅自进行优化。
简单的来说,对访问共享数据的代码块加锁,已经足够保证数据访问的同步性,再加 volatile完全是多此一举。如果光对共享变量使用volatile修饰而在可能存在竞争的
操作中不加锁或使用原子操作对解决多线程竞争没有任何卵用,
volatile并不能保证操作的原子性,在读取、写入变量的过程中仍然可能被其他线程打断导致意外结果发生。
MSDN说得够清楚了:
The volatile keyword in C++11 ISO Standard code is to be used only for hardware access; do not use it for inter - thread ommunication.
volatile int m_nCount;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。