Java 内存模型 JMM 是什么?happens-before 等于代码先执行吗?
下面是一段教学用的模拟面试。
🧑💻 面试官: Java 内存模型是什么?happens-before 怎么理解?
🙋♂️ 我: 就是前面的操作先执行,后面的操作能看到它的结果。
🧑💻 面试官: 线程 A 先写了配置,过了一秒线程 B 才读。没有同步,B 就一定能读到吗?
🙋♂️ 我: 不能只看两个线程实际执行的时间。
🧑💻 面试官: 那你怎样证明配置已经被正确发布?请指出中间的同步关系。
这道题不是让你猜哪个线程先跑,而是让你说明:跨线程的数据,靠什么规则保证对方能看到。
面试速答(60 秒版)
JMM 是 Java 内存模型,它规定多线程程序里,对共享变量的读写允许出现哪些结果,以及同步操作提供什么保证。
happens-before 是判断可见性和顺序的重要关系。如果 A happens-before B,A 的相关效果就应当对 B 可见。它不是两个事件在钟表上谁先发生的记录。
例如,在同一个线程里,前面的操作 happens-before 后面的操作;释放一个监视器锁,happens-before 后续对同一个锁的获取;volatile 写,happens-before 后续对同一个变量的读。关系还可以传递。
实际分析时,要把数据写入、发布动作、接收动作和数据读取连起来。只加 sleep、只看日志时间,不能替代同步。

图:happens-before 不是钟表排序。
知识点详解:配置写完了,对方为什么还不能随便读?
“已经发生”与“有保证”是两回事
假设线程 A 创建一份配置,写入共享字段,再把 ready 标志设成 true。线程 B 等 ready 变成 true,然后读取配置。
如果这些都是普通字段,两个线程没有建立合适的同步关系,那么“机器上试了几次都正常”并不能证明它正确。我们不能把某一次恰好看到的结果,当成内存模型给出的保证。
这里也不必把“工作内存、主内存”画成每个变量必经的物理运输路线。JMM 是语言层面的规则,真实硬件缓存和编译器优化更复杂。
正确的解释,要连起四个动作
仍然用这个发布配置的例子,假设 ready 是 volatile,且这次读取观察到了用于发布配置的那个 true;初始化后也没有其他线程无保护地修改配置。
关系可以这样说清楚:
- A 先写配置,再写 ready,同一线程的程序顺序建立第一段关系。
- A 对 ready 的 volatile 写,与 B 后续的相应 volatile 读建立同步关系。
- B 先读 ready,再使用配置,程序顺序建立第三段关系。
- 根据传递性,前面的配置写入与后面的配置读取连了起来。
重点不是“volatile 会把所有东西神奇地刷一遍”,而是哪些操作之间建立了哪条关系。具体规则可以核对 JLS 第 17 章。
反过来,如果 B 根本没有读取这个发布标志,或者读到的是另一次发布的值,就不能把上面的推理原样套上去。

图:把配置写入和读取连起来。
锁为什么也能完成这件事?
如果 A 在同一个锁的保护下写配置,B 后续获取这个锁再读取,也可以通过解锁、加锁关系传递可见性。
不过必须是同一个监视器。两个名字都叫 lock、实际却不是同一个对象的锁,并不能给这两次访问搭桥。
另外,可见性不是全部问题。如果几个线程同时对一个计数器做“读、加一、写回”,能看到旧值不代表组合操作就是原子的。这个例子仍然需要正确的互斥或原子操作。
为什么日志和 sleep 不能用来证明?
sleep 主要改变调度机会,不给共享字段自动建立需要的同步关系。打印日志可能改变时序,甚至让问题暂时不容易出现,但它不是这段业务数据的设计依据。
正确的排查顺序是先检查共享变量与同步设计,再用压力测试、诊断工具寻找问题。测试没有复现,不等于不存在数据竞争。
本文针对 Java 的规则,不用 TS、Python 的线程 API 冒充 JMM 实现。
面试官继续追问
happens-before 要求底层指令完全不重排吗?
不要求所有底层执行都按源码机械排列。实现可以优化,但不能让程序观察到违反相关保证的结果。
能背出规则,为什么还会写错?
因为知道“volatile 写到读”不等于检查了谁读哪个值、后续对象是否继续被修改。规则需要落到具体的数据流上。
面试速记卡
- JMM:规定共享变量读写与同步的可观察行为。
- happens-before:可见性和顺序关系,不是钟表先后。
- 推理:程序顺序 → 同步关系 → 程序顺序。
- 传递性:把发布前写入与接收后读取连起来。
- 边界:可见性不等于复合操作原子性,sleep 不替代同步。
公司面试真题
真题根据求职者公开面经整理,题意经过概括,非逐字原话或公司官方题库;本文为 Sunday 的独立解析。
美团 · 开发(含 AI 项目追问) · 原帖未明确批次
Java 内存模型怎样工作?(题意整理)
美团面经 ↗
原帖发布于 2025-09-09美团 · Java后端 · 实习
JMM 的原理是什么?(题意整理)
4.21美团Java实习一二面面经 ↗
面试记录为 2020-04-21、2020-04-24;原帖编辑于 2020-11-14