volatile如何保证可见性与有序性

前言

线程安全的四个要素:原子(分为完全原子性,也就是包含了互斥和非完全原子性,也就是不包含互斥)、可见、有序

正文

volatile 对于可见性和有序性的保证是用了 两类 内存屏障(Barrier)来实现的。

首先,内存屏障按保障可见性来划分可分为LoadBarrierStoreBarrierLoadBarrier作用是将其他写线程对于共享变量的更新从其他处理器同步至当前线程的执行处理器,StoreBarrier的作用是保证写线程对共享变量的更新对于其他读线程的执行处理器是可同步的

按照保证有序性来划分,内存屏障可以分为AcquireBarrierReleaseBarrierAcquireBarrier加在读操作后,作用是防止该读操作与屏障后的任何读写操作重排序;而ReleaseBarrier加在写操作之前,作用是防止该写操作和屏障之前的任何读写操作重排序

然后再来看 volatile: 对于volatile写来说:JVM会在其之前插入ReleaseBarrier,这样可以防止其和屏障前的任何读写操作重排序;同时还会在其后插入一个StoreBarrier 这样就可以让此写操作对于其他读线程对应的执行处理器是可同步的
对于volatile读来说:JVM会在其之前插入LoadBarrier,这样其他线程的写操作的结果会同步给当前线程的执行处理器;然后还会在其之后插入AcquireBarrier,这样能防止其与屏障之后的读写操作重排序

参考资料

《Java多线程编程实战指南》