jmm通过volatile、synchronized和final等语言构造隐式插入内存屏障,保障可见性与有序性:volatile读写分别插入loadload+loadstore和storestore+storeload屏障;synchronized进出隐含全屏障;final字段赋值后插入storestore屏障确保安全发布。

volatile 变量读写触发屏障
声明为 volatile 的变量,其每次读写都会由 JVM 自动插入对应屏障:
- volatile 读(
load)前插入 LoadLoad + LoadStore 屏障 → 确保该读操作不会被重排到之前任何读/写之后,且能读到最新值 - volatile 写(
store)后插入 StoreStore + StoreLoad 屏障 → 确保该写操作不会被重排到之后任何读/写之前,并强制刷出到主内存,对其他线程立即可见
这使得 volatile 能实现“轻量级同步”:一个线程写 volatile 变量,另一个线程读它,就能建立 happens-before 关系,无需加锁。
synchronized 块进出隐含全屏障
进入 synchronized 块时,JVM 插入 LoadStore + LoadLoad 类似效果(相当于读屏障);退出时插入 StoreStore + StoreLoad(相当于写屏障+全屏障):
- 进入时:清空工作内存,从主内存重新加载共享变量(保证看到最新状态)
- 退出时:将修改强制写回主内存,并禁止后续指令重排到解锁之前
这就保证了临界区内的所有读写对其他获得同一锁的线程可见且有序。
final 字段写入与构造完成的屏障保障
对象构造中对 final 字段的赋值,JVM 在构造方法结束前插入 StoreStore 屏障:
- 防止该 final 字段的写入被重排到构造函数外
- 确保其他线程通过正确发布(如安全发布、volatile 引用、锁保护)看到该对象时,final 字段值已初始化完毕且不可变
这是实现“安全发布”的关键机制之一,也是 JMM 对不可变性的底层支持。
显式工具类中的屏障调用(慎用)
Java 9+ 提供 VarHandle 的 getAcquire/setRelease 方法,或 Unsafe 的 loadFence()/storeFence(),可手动插入特定屏障:
-
loadFence():等效于 LoadLoad + LoadStore,适合读取多个依赖变量前使用 -
storeFence():等效于 StoreStore,适合批量写入后需保证可见性但不需阻塞后续读的场景
这类 API 性能敏感、语义严格,仅适用于高性能并发库开发,日常业务代码应优先使用 volatile 或锁。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











