并发编程(二十八)指令重排序

137 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第26天,点击查看活动详情

在执行程序时,为了提高性能,编译器和处理器常常会对指令做重排序。重排序分3种类型

1.编译器优化的重排序

通过javac编译成class文件,编译器在单线程情况下且不改变语义的前提下,可以对语句进行一定的重排序,更改语句执行顺序。

2.指令级并行的重排序

现代处理器采用了指令级并行技术(Instruction-Level Parallelism,ILP)来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。

就是在指令执行时,例如A=1,B=2,C=A+B。这时A和B的赋值语句可以并行执行,因为对第三行语句不会造成影响,专业术语叫不存在数据依赖性,此时可以更改语句机器指令执行顺序。

3.内存系统的重排序

由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。

这些数据都会加载到内存中,然后通过内存中的数据进行计算,但是加载和存储只要不影响最后的结果,可以更改顺序,为了提高性能,使计算机提高执行速度。

image.png

从图中我们可以看出一份源代码会经过以上三次重排序,最终得到真正执行的指令序列

对于处理器重排序,JMM的处理器重排序规则会要求 Java编译器 在生成指令序列时,插入特定类型的内存屏障(Memory Barriers,Intel称之为Memory Fence)指令,通过内存屏障指令来禁止特定类型的处理器重排序。