这个问题是在学习 CPU 的缓存一致性中冒出来的。现在网络上大多数对于 volatile 功能的描述是下面这样的:
volatile 提供两大功能:实现线程间共享变量的可见性 + 禁止指令的重排序。这两大功能是通过在对 volatile 变量的操作前后添加对应的内存屏障实现的,内存屏障最粗略分有两类,读内存屏障和写内存屏障,作用分别是从主内存中读取最新的数据和强制将处理器缓存中的数据立即刷新到主内存中。
此外关于为什么会有可见性这个问题,有下面的描述:
多核时代,每颗CPU都有自己的缓存,这时CPU缓存与内存的数据一致性就没那么容易解决了,当多个线程在不同的CPU上执行时,这些线程操作的是不同的CPU缓存。线程 A 修改该线程所在核的缓存中的变量, 线程 B 所见的是该线程所在核的缓存。这样就出现了线程 A 的修改对线程 B 不可见的问题。
但是 MESI 协议在 CPU 层面保证了 CPU 的多个核心中不同缓存(L1/L2 cache)的数据一致性,这和上面的描述明显出现冲突。因为线程 A 在所在核中的修改会传播给线程 B 所在的核中的数据,并修改其状态,使得线程 B 感知到线程 A 的修改。
会出现这样的疑问,是因为对 CPU Cache 机制和读内存屏障/写内存屏障真正的语义的理解有偏差,下面将借此文更新理解》》》》待续