并发编程之指令重排、happens-before

本文探讨了Java中volatile关键字如何防止指令重排序带来的多线程问题。通过内存屏障和happens-before原则,volatile确保了变量在多线程环境中的可见性,从而维护了程序的正确执行。文章列举了先行发生原则的实例,并介绍了多线程编程的八大原则,强调了保证并发安全的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

volatile可以避免指令重排:

指令重排序分两类 编译器重排序和运行时重排序
JVM在编译java代码或者CPU执行JVM字节码时,对现有的指令进行重新排序,主要目的是优化运行效率(不改变程序结果的前提)
int a = 3 //1
int b = 4 //2
int c =5 //3 
int h = a*b*c //4
定义顺序 1,2,3,4
计算顺序  1,3,2,4 和 2,1,3,4 结果都是一样
虽然指令重排序可以提高执行效率,但是多线程上可能会影响结果,有什么解决办法?
解决办法:内存屏障
解释:内存屏障是屏障指令,使CPU对屏障指令之前和之后的内存操作执行结果的一种约束

 happens-before先行发生原则:

先行发生原则,volatile的内存可见性就提现了该原则之一
例子:
//线程A操作
int k = 1;
//线程B操作
int j = k;
//线程C操作
int k = 2
分析:
假设线程A中的操作“k=1”先行发生于线程B的操作“j=k”,那确定在线程B的操作执行后,变量j的值一定等于1,依据有两个:一是先行发生原则,“k=1”的结果可以被观察到;二是第三者线程C还没出现,线程A操作结束之后没有其他线程会修改变量k的值。
但是考虑线程C出现了,保持线程A和线程B之间的先行发生关系,线程C出现在线程A和线程B的操作之间,但是线程C与线程B没有先行发生关系,那j的值会是多少?答案是1和2都有可能,因为线程C对变量k的影响可能会被线程B观察到,也可能不会,所以线程B就存在读取到不符合预期数据的风险,不具备多线程安全性
八大原则
1、程序次序规则
2、管程锁定规则
3、volatile变量规则
4、线程启动规则
5、线程中断规则
6、线程终止规则
7、对象终结规则
8、传递性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值