happens-before本质是可见性保证的逻辑前提而非时间先后;核心规则有四条:程序顺序、volatile变量、锁、线程终止;需用规则链推导写读可见性,不可凭执行顺序猜测。

复习 happens-before 要抓准三个层次:定义本质、规则落地、错误归因。不背条文,重逻辑链;不靠感觉,靠推导。高分关键不是记住八条,而是能用它们判断一段并发代码是否线程安全、变量是否可见。
理解 happens-before 的真实含义
它不是时间先后,是可见性保证的逻辑前提。只要 A happens-before B,那么 A 对共享变量的写,B 一定能读到最新值——哪怕物理上 B 先执行(比如因重排序),JVM 也必须确保这个结果。
考试常设陷阱:问“操作A在时间上早于B,是否一定 happens-before?”答案是否定的。必须依赖规则建立关系,不能凭执行顺序猜测。
八条规则中必须熟练掌握的四条核心
其余四条(中断、终结、传递、启动)可推导或较少单独命题,以下四条是高频考点和解题主力:
- 程序顺序规则:同一线程内,代码位置靠前的操作 happens-before 靠后的操作。注意:仅限单线程内有效,跨线程不自动成立。
- volatile 变量规则:对 volatile 变量的写,happens-before 后续任意线程对该变量的读。这是实现轻量级同步最常用依据,也是面试必问。
- 锁规则(synchronized):一个线程对某锁的 unlock,happens-before 另一个线程后续对该锁的 lock。注意“后续”指时间上紧邻的下一次加锁,不是任意之后。
- 线程终止规则:子线程所有操作 happens-before 主线程调用 thread.join() 返回。这是保障子线程结果被主线程安全读取的底层依据。
用规则组合推导可见性(拿分关键)
真题往往给两段并发代码(如 writer 和 reader 方法),让你判断“reader 是否一定能看到 writer 写的值”。解法固定:
- 先标出关键操作(如 flag = true、x = 42、while(!flag)、print(x))
- 看有没有规则能串起写和读之间的路径(例如:x=42 → flag=true 是程序顺序;flag=true 是 volatile 写;while(!flag) 是 volatile 读 → 由传递性得 x=42 happens-before print(x))
- 若路径断裂(如 flag 非 volatile,且无锁保护),则不可见,存在数据竞争。
画箭头链是最稳妥的应试方法,比口头描述更易得分。
避开高频误区直接提分
这些点几乎每年必考,错一个就丢分:
- volatile 不保证原子性:i++ 这类复合操作即使 i 是 volatile,依然线程不安全。
- final 字段有特殊 happens-before 语义:构造器内对 final 字段的写,happens-before 构造器结束,且该对象引用被其他线程看到之后——这是安全发布对象的基础。
- 没有 happens-before 就没有可见性保证:两个线程各自改普通变量,再各自读,结果完全不确定,编译器和 CPU 都可能重排。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











