volatile 可见性与有序性原理
volatile 是 Java 并发编程的”轻量级”同步机制。它真的轻吗?从 CPU 缓存一致性到指令重排序,一篇文章说清楚。
一、为什么要理解 JMM
- 1.1 物理机缓存模型——CPU → L1/L2/L3 Cache → 主存
- 1.2 缓存一致性问题——MESI 协议简介
- 1.3 Java 内存模型(JMM)抽象——主内存 vs 工作内存
- 1.4 JMM 解决什么——原子性、可见性、有序性
二、volatile 的可见性
- 2.1 写 volatile 变量——立即刷回主内存
- 2.2 读 volatile 变量——强制从主内存读取
- 2.3 一个可见性问题的代码演示
- 2.4 底层实现——Lock 前缀指令与总线锁/缓存锁
三、volatile 的有序性——禁止指令重排序
- 3.1 指令重排序的三种类型——编译器重排、CPU 重排、内存系统重排
- 3.2 happens-before 规则
- 3.3 volatile 写-读建立的 happens-before 关系
- 3.4 双重检查锁定(DCL)单例为什么必须加 volatile
四、内存屏障
- 4.1 Load Barrier / Store Barrier / LoadStore / StoreLoad
- 4.2 volatile 写前后的屏障插入策略
- 4.3 volatile 读前后的屏障插入策略
- 4.4 JVM 层面:
OrderAccess::storeload()的实现
五、volatile 不保证原子性
- 5.1 i++ 的反汇编分析
- 5.2 为什么
volatile int count = 0; count++在多线程下不安全 - 5.3 volatile 适用的场景——状态标志、DCL、独立观察
六、volatile 在并发工具中的应用
- 6.1 AQS 的
state字段 - 6.2 ConcurrentHashMap 的
table数组 - 6.3
CopyOnWriteArrayList的数组引用
七、实战案例
- 7.1 使用 volatile 实现简单的事件监听器
- 7.2 使用 volatile 实现优雅停机
八、总结与 FAQ
- volatile vs synchronized 什么时候用哪个
- 为什么 volatile 不能替代锁
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 谜思录!