问题
在讨论原子性操作时,我们经常会听到一个说法:任意单个volatile变量的读写具有原子性,但是volatile++这种操作除外。
所以问题就是:为什么volatile++不是原子性的?
答案
因为它实际上是三个操作组成的一个符合操作。
- 首先获取volatile变量的值
- 将该变量的值加1
- 将该volatile变量的值写会到对应的主存地址
一个很简单的例子:
如果两个线程在volatile读阶段都拿到的是a=1,那么后续在线程对应的CPU核心上进行自增当然都得到的是a=2,最后两个写操作不管怎么保证原子性,结果最终都是a=2。每个操作本身都没啥问题,但是合在一起,从整体上看就是一个线程不安全的操作:发生了两次自增操作,然而最终结果却不是3。
分析
结合内存屏障这个概念对volatile的读写操作深入理解的话:
第一步:读
在第一步操作的指令后,会增加两个内存屏障:
- 在Volatile读操作后插入LoadLoad屏障,防止前面的Volatile读与后面的普通读重排序
- 在Volatile读操作后插入LoadStore屏障,防止前面的Volatile读与后面的普通写重排序
因此第一个指令和它后续的普通读写操作会被保证没有重排序来捣乱。通常是去内存中去读。
那么问题又来了,为什么通常去内存中读?
其实这个问题要说细的话可以很细,大概就两个关键点吧:
- volati