news 2026/4/30 18:04:14

【Java-JMM】Happens-before原则

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Java-JMM】Happens-before原则

心理解:如果操作 A happens-before 操作 B,那么 A 的执行结果对 B 可见。这个原则主要解决了 Java 并发编程中的两个关键问题:

可见性问题:由 CPU 缓存引起

有序性问题:由编译器优化和指令重排引起

二、Happens-before 的具体规则#

1. 程序顺序性规则#

在单线程中,按照程序代码顺序,前面的操作 happens-before 后面的操作。

关键点:

有依赖关系:操作间存在数据依赖时,顺序不可重排

无依赖关系:操作间无数据依赖时,可以重排序,但要保证单线程执行结果不变

int a = 1; // 操作A

int b = 2; // 操作B(与A无依赖,可重排)

int c = a + 1; // 操作C(依赖A,必须在A之后)

int d = b * 2; // 操作D(依赖B,必须在B之后)

// 可能的执行顺序:

// ✓ A → B → C → D(原始顺序)

// ✓ B → A → C → D(B与A无依赖,可交换)

// ✗ C → A → B → D(C依赖A,不能在A之前)

2. volatile 变量规则#

对 volatile 变量的写操作 happens-before 后续对该变量的读操作。

volatile int flag = 0;

// 线程A

flag = 1; // 写操作

// 线程B

if (flag == 1) { // 读操作

// 能看到线程A的写入

}

3. 传递性规则#

如果 A happens-before B,且 B happens-before C,那么 A happens-before C。

4. 锁规则(Monitor Lock Rule)#

对一个锁的解锁操作 happens-before 后续对这个锁的加锁操作。

synchronized (lock) {

// 临界区代码

} // 解锁

// 其他线程

synchronized (lock) { // 加锁

// 能看到前一个线程在临界区的所有操作

}

5. 线程启动规则#

线程 A 中调用线程 B 的 start() 方法之前的所有操作,happens-before 线程 B 中的任意操作。

6. 线程终止规则#

线程 B 中的所有操作 happens-before 线程 A 中调用 B.join() 方法成功返回后的操作。

public class VisibilityDemo {

static int var = 0;

public static void main(String[] args) throws InterruptedException {

// 主线程操作

var = 10; // ① 主线程修改

Thread B = new Thread(() -> {

// 子线程B能看到①的修改(线程启动规则)

var = 66; // ② 子线程修改

});

B.start(); // 启动子线程

B.join(); // 等待子线程结束

// ③ 主线程能看到②的修改(线程终止规则)

System.out.println(var); // 输出:66

}

}

执行流程:

根据线程启动规则:主线程的 var = 10 happens-before 子线程 B 的所有操作

根据线程终止规则:子线程 B 的 var = 66 happens-before 主线程 join() 之后的操作

因此主线程最终能看到 var 的值为 66

7. final 字段规则#

在构造函数中对 final 字段的写入,happens-before 其他线程对该对象的 final 字段的读取。

public class FinalExample {

private final int value;

public FinalExample(int value) {

this.value = value; // 构造函数中的写入

}

// 其他线程读取时,保证能看到构造函数中的赋值

public int getValue() {

return value;

}

}

三、总结#

Happens-before 原则是 Java 并发编程的基石,它通过定义操作间的可见性关系,让开发者能够在不了解底层硬件细节的情况下,编写正确的并发程序。掌握这些规则,是写出线程安全代码的关键。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 8:20:39

请教软件和业务问题,引发的思考

我是一名只会CURD的后端搬运工,在我的思维里面,只有业务规则,业务流程,以及原型图,UI,开发框架等。​ 如何深入的了解软件项目中的业务,一直是心中的疑问,在一次分享讨论技术的会议中…

作者头像 李华
网站建设 2026/4/23 14:15:03

轻量级图片信息解析程序

平时的工作中我经常需要获取图片文件的一些基本信息(宽度、高度、通道数、色深)。因为项目依赖 opencv,以前都是直接用的 opencv 来读入图片后获取这些信息的,opencv 读入图片是读取所有的数据,会影响效率和内存占用&a…

作者头像 李华
网站建设 2026/4/28 6:09:22

RFSOC学习记录(五)带通采样定理

onverter这个ip核里面三种混频模式从底层上的了解,这一篇主要记录一下带通采样定理的知识,下一篇会涉及到三种混频模式的配置不同在这里采样和频谱混叠等本科基础知识就不再赘述,直奔主题带通采样定理我们在大学课堂里学习的奈奎斯特采样定理…

作者头像 李华
网站建设 2026/5/1 7:24:20

动态 IP 在爬虫、跨境电商如何避开封禁陷阱

在数据驱动的时代,无论是爬虫采集还是跨境电商运营,都绕不开一个现实问题: 👉 IP 被封禁。从搜索引擎、社交媒体、电商平台到广告投放系统,反爬与风控机制日益成熟,单一 IP、高频请求、异常行为都会迅速触发…

作者头像 李华
网站建设 2026/5/1 7:18:15

我的256天创作纪念日

【摘要】 256天,正好是2的8次方。在计算机的世界里,它代表一个完整的字节(Byte)。于我而言,这也是一个从零散的技术点,向完整的架构知识体系汇聚的关键节点。本文回顾了从Flowable与AI实战,到拿…

作者头像 李华