volatile通过MESI协议和内存屏障保障可见性与有序性:写操作触发RFO使其他核缓存行置为Invalid,读操作因失效强制重载最新值;同时插入StoreLoad/LoadLoad等屏障禁止重排序,但不保证复合操作原子性。

volatile 通过触发硬件级缓存一致性协议(主要是 MESI),强制刷新和失效操作,来保障多核 CPU 下的缓存一致性。
底层依赖 MESI 协议
现代多核 CPU 每个核心都有私有缓存(L1/L2),共享变量可能被多个核心各自缓存。当一个核心修改 volatile 变量时,JVM 会生成带 lock 前缀的汇编指令(如 lock xadd),该指令在硬件层面触发 MESI 协议的状态转换:
- 当前核心将对应缓存行状态置为 Modified(M),并标记该数据与主内存不一致;
- 同时通过总线广播 Invalidate(失效)消息,使其他核心中该变量所在缓存行状态变为 Invalid(I);
- 下次其他核心读取该变量时,发现缓存行已失效,必须重新从主内存(或拥有 M/E 状态的核心)加载最新值。
绕过工作内存直通主内存
JMM 规定:对 volatile 变量的每次读操作,都必须从主内存重新加载;每次写操作,都必须立即刷新到主内存。
- 这相当于禁用了线程工作内存对该变量的“缓存副本”——不是真的删掉缓存,而是用内存屏障 + 协议强制它失效后重载;
- 避免了普通变量可能出现的“线程 A 写了,线程 B 还在用旧缓存值”的可见性问题。
配合内存屏障禁止重排序
volatile 写操作前后插入内存屏障(StoreStore 和 StoreLoad),volatile 读操作前后插入(LoadLoad 和 LoadStore):
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
立即学习“Java免费学习笔记(深入)”;
- 防止编译器和 CPU 将 volatile 读/写与其它内存操作重排序;
- 确保“写 volatile 之前的所有写操作”对后续读到该 volatile 的线程可见(happens-before 语义);
- 这对 DCL(双重检查锁定)单例等场景至关重要——保证对象构造完成后再发布引用。
注意:不保证原子性
volatile 只解决可见性和有序性,不解决复合操作的原子性。例如 i++(读-改-写)即使 i 是 volatile,仍可能丢失更新:
- 两个线程同时读到 i=1;
- 各自加 1 得到 2;
- 先后写回主内存,最终 i=2 而非预期的 3。
这类操作需用 synchronized、Lock 或 AtomicInteger 等机制保障原子性。

















