volatile
- volatile使得代码每次在读写volatile变量时都需要从内存读写,而不能使用寄存器中缓存的值。并且也禁止编译器对volatible做编译优化。volatile本身并不是用于线程同步,也不保证原子读写(例如volatile a++这种需要几个指令才能完成的操作)。volatile主要用于access to memory mapped devices和variables in signal handlers and between setjmp and longjmp。C++标准禁止编译器reorder同一个线程内的volatile变量的读写,但不同线程则没有限制。non-volatile变量则有可能发生reorder(Stay away from Volatile in threaded code?)。
- 而根据为什么volatile++不是原子性的?中的说法,volatile的读操作后会插入LoadLoad和LoadStore屏障,避免volatile读操作与后面的普通读写发生reorder。而volatile的写操作前会插入StoreLoad和StoreStore屏障,避免volatile写操作与后面的普通读写发生reorder(我不太确定这种说法的正确性,毕竟在wikipediavolatile (computer programming)中并没有提到volatile会插入内存屏障,或者只有Java等语言才会这样做?)。
- 内存屏障中有提到
C与C++语言中,volatile关键字意图允许内存映射的I/O操作。这要求编译器对此的数据读写按照程序中的先后顺序执行,不能对volatile内存的读写重排序。因此关键字volatile并不保证是一个内存屏障。[4]
对于Visual Studio 2003,编译器保证对volatile的操作是有序的,但是不能保证处理器的乱序执行。因此,可以使用InterlockedCompareExchange或InterlockedExchange函数。
对于Visual Studio 2005及以后版本,编译器对volatile变量的读操作使用acquire semantics,对写操作使用release semantics。