C/C++中:
编译器在编译程序的时候会对程序指令做一些优化,如改变一些指令的执行顺序,或者把变量的值拷贝到寄存器中,然后在接下来的使用中从寄存器中快速的取得该值。
然而这些优化行为有可能在多线程环境中造成临界区数据竞赛,想象一下两个线程A,B都在访问一个变量C,当A在访问变量C时,编译器做了优化,将C的值拷贝到了寄存器中已备告诉访问,问题来了,如果B改变了C变量的值,而A访问的依旧是缓存的值,就有可能造成数据的不一致。
volatile修饰符告诉编译器不要对此变量进行任何优化操作,但这并不足以同步线程,因为他缺少原子性和顺序性的语义。
例如i++操作,其实是有三个操作组成的,首先从内存中将值加载到寄存器中,然后将值加1,再写到寄存器中,因为volatile并没有原子性的语义,所以用volatile声明的变量i,仍然面临多线程环境下的数据不一致问题。
volatile没有顺序性的语句,所以他申明的变量设计的操作有可能被重新排列执行顺序以增加性能,这样容易引起数据竞赛。
Java:
Java中的volatile相比c、c++要强大,在1.5以后加入了不完全的顺序语义:
1.在读取volatile变量时,读取操作之后的操作必须在当前读取操作完成之后才能执行。
2.在写volatile变量时,在这个操作之前的操作必须限执行完毕以后,本操作才能执行。
这个不完全的顺序语义,可以让java中volatile变量用来做多线程建的状态标记。
C#与Java类似。
综上所述,volatitle 在线程同步方面比较弱。