C++关键字-volatile
volatile
关键字是一种类型修饰符。
volatile int a;
volatile原义:
A situation that is volatile is likely to change suddenly and unexpectedly.
- likely:可能的。这意味着被 volatile 形容的对象「有可能也有可能不」发生改变,因此我们不能对这样的对象的状态做出任何假设。
- suddenly:意味着被 volatile 形容的对象可能发生瞬时改变。
- unexpectedly:意味着被 volatile 形容的对象可能以各种不可预期的方式和时间发生更改。
因此,volatile
其实就是告诉我们,被它修饰的对象出现任何情况都不要奇怪,我们不能对它们做任何假设。
程序中volatile的含义
1. volatile修饰的对象可能受到程序之外的因素影响
这里说的程序之外的因素影响可以是操作系统、硬件或者其它线程等。
int a = 0;
int b = a;
在上述代码中,当执行b = a
语句时,编译器会判断在a赋值以后就没有改变过a的值,
因此会把寄存器中暂存的a的值给b,而不是去a的内存地址处去读取a再赋值给b。
一般情况这样是没问题的,但是当有中断程序或者别的进程去修改了a的值,那寄存器里暂存的a就会和内存里存放的a不一致。
加了volatile
限定符,每次使用a时都会去a的内存地址处读取a,这样能保证每次读取的a都是最新的值;但同时会导致效率降低,因为读取内存的速度远低于读取寄存器的速度。
2. volatile修饰的对象不允许被编译器optimized out
volatile int num;
num = 1;
printf("num is: %d", num);
在上述代码中,如果变量 num
没有声明为 volatile
类型,则编译器在编译过程中就会对其进行优化,直接使用常量“1”进行替换。
当使用 volatile
进行声明后,编译器则不会对其进行优化。
3. volatile修饰的对象能够保证不会被编译器调整执行顺序
编译器编译时可能会调整代码的执行顺序
编译器虽然能保证不对volatile变量执行顺序进行优化,但是不能保证对volatile
变量与非 volatile
变量之间的操作的执行顺序不优化。
但是,volatile
只作用在编译器上,但我们的代码最终是要运行在 CPU 上的。尽管编译器不会调整执行顺序,但 CPU 的乱序执行(out-of-order execution)技术还是可能导致代码的执行顺序被改变。
volatile用法
volatile
只在三种场合下是合适的:
- 和信号处理(signal handler)相关的场合;
- 和内存映射硬件(memory mapped hardware)相关的场合;
- 和非本地跳转(
setjmp
和longjmp
)相关的场合。
volatile与多线程
volatile不能解决多线程中的问题