volatile
起源
volatile
是用来处理memory-mapped I/O(MMIO)
,带来的问题,在引入MMIO
之后,一个内存地址既可能是真正的内存,也可能是被映射到一个I/O
端口。相对于读写一个内存地址,即有可能是读写真正的内存,又有可能是读写的是一个I/O
设备。
考虑如下情形,
int *p = some address;
int a, b;
a = *p;//读操作
b = *p;
*p = a;//写操作
*p = b;
volatile
的三个性质
1.易变性
如果p
指向的是I/O
设备,那么两次读取数据都要从地址读,并且两次读取到两个连续的字节。
2.不可优化
如果不使用volatile
,那么编译器发现连续对*p
赋值,可能会把第一个省略掉,这对I/O
设备来说是不正确的。
3.顺序性
如果不加volatile
那么*p = b;
可能会比*p = a;
先执行,这对于I/O
设备来说是不正确的。
总结
多线程同步需要的是happen before
语义,volatile
关键字并不能提供这个语义,多线程编程中小心使用volatile
。