happens-before是JMM提供的内存可见性承诺,非时间先后而是逻辑因果;如volatile写happens-before读,确保结果可见;程序顺序、volatile变量、监视器锁、线程启动四规则各配代码实例,并解释其如何解决双重检查单例重排、锁外判断可见性等实际问题。

面试中讲清楚 happens-before,关键不是背规则,而是说清它“为什么存在”和“怎么用”。一句话点题:happens-before 是 JMM 给程序员的**内存可见性承诺**,不是时间先后,而是逻辑因果。
先破误区:别把它当执行顺序
很多候选人一开口就说“A 操作发生在 B 操作之前”,这是典型误解。要强调:happens-before 描述的是结果可见性与操作约束关系,不等于物理时间顺序。比如 volatile 写后读,即使 CPU 实际执行有延迟,JMM 也保证读能看见写的结果——这才是它的价值。
讲清四大高频规则,带例子不空谈
挑面试官最常问的四条讲透,每条配一句代码级说明:
-
程序顺序规则:同一线程里,代码上靠前的语句 happens-before 靠后的语句。例如
int a = 1; int b = a + 1;,a 赋值一定对 b 计算可见。 -
volatile 变量规则:对 volatile 变量的写 happens-before 后续对该变量的读。这是实现轻量级状态通知的基础,比如用
volatile boolean ready = false控制初始化完成。 - 监视器锁规则:一个线程 unlock 锁 happens-before 另一个线程 lock 同一把锁。synchronized 块进出之间,共享变量修改才对下一个持锁线程可见。
-
线程启动规则:主线程调用
t.start()的动作 happens-before 子线程的任意操作。所以初始化参数、设置标志位放在线程启动前,子线程一定能看见。
联系实际问题,体现理解深度
别只列规则,要扣住并发痛点:
- 解释为什么双重检查单例需要
volatile:防止new Singleton()的指令重排(分配内存 → 设置引用 → 执行构造),导致其他线程拿到未初始化完成的对象。 - 说明为什么仅加锁不够:锁只保护临界区,但锁外的判断(如
if (instance == null))依赖的是可见性,这正是 happens-before 要兜底的地方。 - 点出它和内存屏障的关系:volatile/synchronized 的底层就是插入不同类型的内存屏障(LoadLoad、StoreStore 等),让编译器和 CPU 不敢乱序。
收尾点明定位:它是 JMM 的契约,不是实现细节
最后可以补一句:JMM 不规定 JVM 怎么实现,只规定必须满足 happens-before 承诺。编译器可以重排序,CPU 可以缓存,只要最终表现符合这些规则,就合法。这样既显格局,又区分了“规范”和“实现”。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











