happens-before锁定规则的核心是:一个线程对锁的unlock操作happens-before另一线程对同一把锁的lock操作,确保unlock前所有写操作对后续加锁线程可见,本质是通过内存屏障强制刷新和重读实现跨线程同步。

Java 内存模型中,happens-before 的锁定规则核心是:一个线程对锁的 unlock 操作 happens-before 另一个线程对 同一把锁的 lock 操作。它不关心物理时间谁先谁后,而是确保“解锁前的所有写操作”对“后续加锁的线程”可见。
锁定规则的本质是同步边界
这是一条跨线程的可见性保障机制,不是调度指令,也不是强制等待。它的作用是划出一条内存同步的分界线:
- synchronized 块退出(unlock)时,JVM 必须将该线程本地缓存中所有被修改过的共享变量,刷新回主内存
- 另一线程进入同一把锁的 synchronized 块(lock)前,必须从主内存重新读取这些变量的最新值
- 因此,前一线程在临界区内做的所有修改,对后一线程“必然可见”
它解决什么问题?
没有这条规则,两个线程可能各自在 CPU 缓存里读写变量,互不知情。比如:
- 线程 A 在 synchronized 块内把
count = 100 - 线程 B 在另一个 synchronized 块里读
count - 若无锁定规则,B 可能永远读到旧值 0 —— 因为 A 的写没刷出,B 的读没拉新
有了锁定规则,A 的 unlock 和 B 的 lock 构成 happens-before 关系,JVM 就必须保证 B 看到 A 的全部更新。
注意几个关键点
这条规则生效有明确前提:
-
必须是同一把锁对象:用
new Object()创建的不同锁,不构成该关系 - 不是“加锁前的操作”都可见:只有发生在 unlock 之前的写才被保证;unlock 之后、锁释放后的写,不在此保障范围内
- 不依赖执行时间先后:即使线程 B 在 A 还没 unlock 时就尝试 lock(发生阻塞),只要最终 B 成功获取了锁,unlock → lock 的 happens-before 关系就成立
它如何与其他规则配合?
锁定规则常和程序顺序规则、传递性组合使用。例如:
- 线程 A:
synchronized(lock) { data = 42; flag = true; }→ unlock - 线程 B:
synchronized(lock) { if (flag) System.out.println(data); }
由于 unlock → lock 成立,且 data = 42 happens-before unlock(程序顺序),再通过传递性,得到 data = 42 happens-before B 的读取,所以 B 一定能打印出 42。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











