直接回答:Java 内存模型(JMM)是 JLS 定义的规范,抽象出"主内存 + 每个线程的工作内存"的结构,规定多线程下变量的读写规则,核心围绕原子性、可见性、有序性三个问题。happens-before 是 JMM 提供给开发者的可见性保证:若操作 A happens-before 操作 B,则 A 的结果对 B 可见,且 A 在排序上先于 B。

展开解析:常见的 happens-before 规则:

  • 程序次序:单线程内前面的操作先于后面的操作;
  • 监视器锁:对同一锁的 unlock 先于后续的 lock;
  • volatile:对 volatile 变量的写先于后续对它的读;
  • 线程规则thread.start() 之前的操作先于线程内任何操作;线程中的所有操作先于其他线程从 join() 返回;
  • 传递性:A 先于 B、B 先于 C,则 A 先于 C。

易错点:happens-before 不等于真实的时间先后,它是"结果可见"的承诺,编译器只要不违反它就可以重排。JMM 的意义在于让 Java 程序在不同 CPU 架构(缓存一致性、乱序执行各异)上有统一的并发语义。

追问方向:为什么单例 DCL 需要 volatile、final 字段的安全发布语义、as-if-serial 与 happens-before 的关系。