怎么通过 Happens-before 传递性规则理解为何线程 A 的 lock.unlock() 能够同步线程 B 的 lock.lock()?

冬晨小哥_5135

冬晨小哥_5135

2026-04-27

398人浏览

原创

unlock() 与后续同一锁的 lock() 存在 happens-before 关系,而非任意 unlock 与 lock;其可见性依赖传递性链:写操作→unlock→lock→读操作,且须满足同锁、时序正确、写在临界区内三前提。

怎么通过 happens-before 传递性规则理解为何线程 a 的 lock.unlock() 能够同步线程 b 的 lock.lock()?

unlock() 和 lock() 之间没有直接 happens-before 关系

很多人误以为 unlock() 本身“天然地” happens-before 后续的 lock(),这是错的。JMM 并不规定“任意 unlock 都 happens-before 任意 lock”。真正成立的是:**对同一个锁对象的 unlock() happens-before 后续对该同一锁对象的 lock()** —— 关键在“同一个锁”和“后续”(时间上发生在其后)。

传递性才是同步生效的核心机制

假设线程 A 执行完临界区并释放锁,线程 B 随后获取该锁并进入临界区。要让线程 B 看到线程 A 对共享变量的修改,靠的不是 unlock→lock 这一对动作的直接关系,而是两条独立的 happens-before 链通过传递性拼接:

  • 线程 A 中,x = 42(写共享变量) happens-before unlock()(程序次序规则)
  • unlock()(线程 A) happens-before lock()(线程 B,同一锁,且时间上在其后)(监视器锁规则)
  • 于是由传递性得:x = 42 happens-before lock()(线程 B)
  • 而 lock() happens-before 线程 B 中临界区内的任意操作(比如 System.out.println(x))(程序次序规则)
  • 最终:x = 42 happens-before System.out.println(x) → 线程 B 一定能读到 42

容易忽略的关键约束

这条链能成立,依赖三个不可妥协的前提:

  • 必须是**同一个锁对象**:用 new Object() 分别 new 出两个锁,unlock() 和 lock() 就无法建立 happens-before
  • 必须存在**实际的执行时序**:unlock() 真的在 lock() 之前完成;如果线程 B 在 A 还没 unlock 前就抢到了锁(比如锁被重入或有竞争失败重试),链就断了
  • 共享变量必须在**临界区内修改**:如果 x = 42 写在 synchronized 块外面,它和 unlock() 之间就没有程序次序保障,整条链失效

volatile + 程序次序也能构造等效链,但语义不同

不用锁,也能靠 volatile 和传递性达成类似效果,例如:

static volatile boolean ready = false;
static int data = 0;
<p>// 线程 A
data = 42;          // A1
ready = true;       // A2 → happens-before 后续所有对 ready 的读</p><p>// 线程 B
while (!ready) {}   // B1 → A2 happens-before B1(volatile 规则)
System.out.println(data); // B2 → B1 happens-before B2(程序次序)
// 由传递性:A1 happens-before B2 → data 可见
</p>

这里没用锁,但依然靠两段 happens-before(A1→A2、A2→B1、B1→B2)串起完整可见性链。区别在于:锁提供互斥+可见性,volatile 只提供可见性+禁止重排序,不保证原子性。

真正难的不是记住八条规则,而是每次写并发逻辑时,都得亲手画出那条从写到读的 happens-before 链——漏掉任一环,就可能在某个 CPU 缓存层级上看到过期值。

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.15

10777

6

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

2023.07.05

7882

9

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

2023.07.31

6852

8

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.01

1164

3

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.02

948

3

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

1396

5

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

2829

5

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

2023.08.03

20131

3

配置java环境变量
配置java环境变量

配置Java环境变量是为了让操作系统能够识别和使用Java的相关命令和功能。本专题为大家提供配置java环境变量相关文章,帮助大家解决问题。

2023.08.03

1255

8

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.8万人学习