volatile的有序性问题
volatile关键字使用禁止指令重排序,在一定程度上保证了有序性。
指令重排
计算机在执行程序时,为了提高性能,编译器和处理器常常会对指令做重排,一般分为以下3种:
源代码 --> 编译器优化的重排 --> 指令并行的重排 --> 内存系统的重排 --> 最终执行的指令
单线程环境里确保程序最终执行结果和代码顺序执行的结果一致。
处理器在进行重排序时要考虑指令之间的数据依赖性。
多线程环境中线程交替执行,由于编译器优化重排的存在,两个线程中使用的变量能否保证一致性是无法确定的,结果无法预测。
禁止指令重排
volatile实现禁止指令重排优化,从而避免多线程环境下出现乱序执行的现象
先了解一个概念,内存屏障(Memory Barrier)又称内存栅栏,是一个CPU指令,它的作用有两个:
一是保证特定操作的执行顺序,
二是保证某些变量的内存可见性(利用该特性实现volatile的内存可见性)。
由于编译器和处理器都能执行指令重排优化。如果在指令间插入一条Memory Barrier则会告诉编译器和CPU,不管什么指令都不能和这条Memory Barrier指令重排序,也就是说通过插入内存屏障禁止在内存屏障的前后的指令执行重排序优化。内存屏障另外一个作用是强制刷出各种CPU的缓存数据,因此任何CPU上的线程都能读取到这些数据的最新版本。