happens-before是Java内存模型定义的可见性契约,不保证执行时间先后,只承诺若A happens-before B,则A对共享变量的修改对B一定可见且完整;它通过程序顺序、volatile、锁、线程启动/终止等规则及传递性构建跨线程可见路径,但不保证原子性或多变量间逻辑约束。

Java 中 happens-before 规范不直接“保障一致性”,而是通过建立操作间的可见性契约,让程序员能明确知道:当满足某条规则时,前一个线程的写入结果,对后一个线程的读取一定是可见的——这是实现读写一致性的底层基础。
它解决的核心问题是“看到什么”
多线程下,变量修改可能滞留在 CPU 缓存或写缓冲区,未及时刷到主内存;编译器或处理器还可能重排序指令。结果就是:线程 A 写了 x=1,线程 B 却读到 x=0,甚至读到半个 long 值(字长撕裂)。happens-before 不承诺执行时间先后,只承诺:如果 A happens-before B,B 就一定能看到 A 的完整、最新结果。
靠规则链构建跨线程可见路径
单个规则无法覆盖复杂场景,真正起作用的是规则之间的传递性——把多个局部保证串成一条逻辑链:
- 线程 A 在 synchronized 块内写 sharedVar = 42,然后释放锁 → 解锁 happens-before 线程 B 后续对该锁的加锁
- 线程 B 加锁后读 sharedVar → 因为加锁 happens-after 解锁,所以能安全看到 42
- 若再配合 volatile flag 控制流程(flag 写 happens-before flag 读),就能把普通变量的写和 volatile 的读连成完整链
常见规则如何分别支撑读写行为
程序顺序规则:同一线程内,x = 1 happens-before print(x),确保单线程内不会“先读后写”乱序。
监视器锁规则:synchronized 块退出(unlock)happens-before 下一个线程进入同一把锁(lock),保证临界区写入对后续进入者可见。
volatile 变量规则:flag = true(volatile 写)happens-before while(!flag)(volatile 读),以此为“信标”,把其前后的普通读写纳入可见范围。
线程启动/终止规则:t.start() happens-before t 中第一行代码;t 中最后一行 happens-before main 中 t.join() 返回,适合初始化与收尾阶段的数据传递。
注意它不做什么
happens-before 不保证原子性。比如 i++ 是读-改-写三步,即使 i 是 volatile,也不能防止两个线程同时读到相同旧值;它也不自动约束多个变量间的逻辑关系(如“写 a 后必须写 b”),这类需靠锁或更高层同步机制。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











