重排序
重排序:编译器和处理器为了优化程序性能而对指令序列重新排序的一种手段
1. 数据依赖性
定义:如果两个操作访问同一个变量,且这两个操作中有一个为写操作,则这两个操作存在数据依赖性
数据依赖性类型表
名称 | 代码示例 | 说明 |
---|---|---|
写后读 | a = 1; b = a; | 写一个变量之后,再读这个位置 |
写后写 | a = 1; a = 2; | 写一个变量之后,再写这个变量 |
读后写 | a = b; b = 1; | 读一个变量之后,再写这个变量 |
重排序时,编译器和处理器不会更改存在数据依赖性关系的两个操作的执行顺序
适用范围:单个处理器中执行的指令和单个线程中执行的操作
2. as-if-serial语义
含义:无论怎样重排序,单线程程序的执行结果不能被改变
编译器、处理器、runtime都必须遵守该语义
为了遵守该语义,编译器和处理器的重排序规则会按照两个操作间有无数据依赖性进行
3. 程序顺序规则
JMM要求前一个操作(执行的结果)对后一个操作可见,且前一个操作按顺序排在第二个操作之前
软件技术和硬件技术共同的目标:在不改变程序执行结果的前提下,尽可能提高并行度
4. 重排序对多线程的影响
当代码中存在控制依赖性时,会影响指令序列执行的并行度,这种情况下编译器和处理器会采用猜测执行来克服该影响。
在单线程程序中,对存在控制依赖的操作重排序不会改变执行结果,但在多线程程序中可能会改变执行结果