并发编程-重排序
2021/5/11 22:55:09
本文主要是介绍并发编程-重排序,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
并发编程-重排序
目录- 并发编程-重排序
- 一、数据依赖性[相关]
- 二、as-if-serial 语义
- 三、程序顺序规则
- 四、重排序对多线程的影响
重排序是指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段。
一、数据依赖性[相关]
若两个操作访问同一变量,且有一个为写操作,此时产生数据依赖性。数据以来分为下列 3 中类型:
名称 | 代码示例 | 说明 |
---|---|---|
写后读 | a = 1; b = a; | 先写后读 |
写后写 | a = 1; a = 2; | 先写后写 |
读后写 | a = b; b = 1; | 先读后写 |
上述三种情况,只要重排序两个操作的执行顺序,程序的执行结果都将被改变。
一般情况,编译器和处理器可能会对操作进行重排序,但若存在数据依赖关系,就不会进行重排序。
二、as-if-serial 语义
as-if-serial 语义:不管怎么重排序,程序的执行结果不能被改变。编译器、runtime、处理器都必须遵守 as-if-serial 语义。
为了遵守 as-if-serial 语义,编译器和处理器不会对存在数据依赖关系的操作重排序,因为这种重排序会改变执行结果。若操作间不存在数据依赖关系,这些操作九可能被编译器和处理器重排序。
例如:
double pi = 3.14; //A double r = 1.0; //B double area = pi * r * r; //C
上边 3 个操作的数据依赖关系如图:
如图所示,A 和 C 之间存在数据依赖关系,同时 B 和 C 之间也存在数据依赖关系。因此在最终执行的指令序列中,C 不能重排序到 A 和 B 的前面(C 排到 A 和 B 的前面,执行结果也将改变)。但 A 和 B 之间不存在数据依赖关系,编译器和处理器可以重排序 A 和 B 之间的执行顺序。
下图是该程序的两种可能会出现的执行顺序:
as-if-serial 语义把单线程程序保护了起来,遵守 as-if-serial 语义的编译器、runtime 和处理器共同为编写单线程程序的程序员创建了一个幻觉;单线程程序是按程序的顺序来执行的。as-if-serial 语义使单线程程序员无需担心重排序会干扰他们,也无需担心内存可见性问题。
三、程序顺序规则
根据 happens-before 的程序顺序规则,上面计算圆的面积的示例代码存在 3 个 happens-before 关系。
- A happens-before B
- B happens-before C
- A happens-before C
这里的第三个 happens-before 关系,是根据 happens-before 的传递性推导出来的。
这里 A happens-before B,但实际执行时,B 可以排在 A 之前执行。如果 A happens-before B,JMM 并不要求 A 一定要在 B 之前执行。JMM 仅仅要求前一个操作(执行的结果)堆后一个操作可见,且前一个操作按顺序排在第二个操作之前。这里操作 A 的执行结果不需要对操作 B 可见;而且冲排序操作 A 和操作 B 后的执行结果,与操作 A 和操作 B 按 happens-before 顺序执行的结果一致。这种情况下,JMM 会认为这种冲排序并不非法,JMM 允许这种重排序。
四、重排序对多线程的影响
现在看一个示例,验证重排序是否会改变多线程程序的执行结果。
class RecordExample{ int a = 0; boolean flag = false; public void writer(){ a = 1; flag = true; } public void reader(){ if (flag){ int i = a * a; } } }
这篇关于并发编程-重排序的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-10-05小米13T Pro系统合集:性能与摄影的极致融合,值得你升级的系统ROM
- 2024-10-01基于Python+Vue开发的医院门诊预约挂号系统
- 2024-10-01基于Python+Vue开发的旅游景区管理系统
- 2024-10-01RestfulAPI入门指南:打造简单易懂的API接口
- 2024-10-01初学者指南:了解和使用Server Action
- 2024-10-01Server Component入门指南:搭建与配置详解
- 2024-10-01React 中使用 useRequest 实现数据请求
- 2024-10-01使用 golang 将ETH账户的资产平均分散到其他账户
- 2024-10-01JWT用户校验课程:从入门到实践
- 2024-10-01Server Component课程入门指南