并发编程(五)指令重排序
文章更新时间:2021/07/08
一、数据依赖性
在学习JVM的指令重排序之前,我们先了解一下什么是数据依赖性:
编译器和处理器在处理具体的指令时,可能会对操作进行重排序来提高执行性能【多条指令并行执行,所以提升性能的同时也可能会导致指令乱序】;而上面3种情况,只要重排序两个操作的执行顺序,程序的执行结果就会被改变。
编译器和处理器在重排序时,会遵守数据依赖性,编译器和处理器不会改变存在数据依赖关系的两个操作的执行顺序。
PS:这里所说的数据依赖性仅针对单个处理器中执行的指令序列和单个线程中执行的操作,不同处理器之间和不同线程之间的数据依赖性不被编译器和处理器考虑。
二、相关规则
as if serial语义
定义:不管怎么重排序(编译器和处理器为了提高并行度),(单线程)程序的执行结果不会改变。
解析:编译器、runtime和处理器都必须遵守as-if-serial语义。 为了遵守as-if-serial语义,编译器和处理器不会对存在数据依赖关系的操作做重排序,因为这种重排序会改变执行结果。 但是,如果操作之间不存在数据依赖关系,这些操作就可能被编译器和处理器重排序。
happen-before原则
定义:一个线程中的每一个操作happens-before于该线程的任意后续操作,这里的happens-before并不是前一个操作必须早于后一个操作, 而是前一个操作必须对后一个操作可见,否则不能重排序。
程序次序规则
定义:一段程序代码的执行在单个线程中看起来是有序的,不过因为虚拟机可能会对程序代码进行指令重排序,虽然进行重排序,但是最终执行的结果是与程序顺序执行的结果一致的。
三、重排序对多线程的影响
我们前面知道了,在单线程运行中,指令重排序不能影响程序执行的结果,但是在多线程的运行中,指令重排序可能会影响程序的执行结果的,我们通过一张图来直观地观察一下:
那么我们来看一下正常运行状态下和重排序状态下的时间线:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)