前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Java 并发编程】指令重排序规范 ( happens-before 先行发生原则 )

【Java 并发编程】指令重排序规范 ( happens-before 先行发生原则 )

作者头像
韩曙亮
发布2023-03-29 16:50:57
2450
发布2023-03-29 16:50:57
举报
文章被收录于专栏:韩曙亮的移动开发专栏

文章目录

一、指令重排序规范


指令重排指的是 , 线程中如果两行代码 没有逻辑上的上下关系 , 可以对代码进行 重新排序 ;

JVM 指令重排遵循规范 :

① as-if-serial 规范 : 单个线程中, 指令的重排 , 不能影响程序的执行结果 ;

  • 可以重排的情况 : 对于下面代码 , 两条指令顺序颠倒 , 执行结果相同 , 可以进行指令重排 ;
代码语言:javascript
复制
x = 0;
y = 1;
  • 不可以进行重排的情况 : 对于下面的代码 , 两条指令如果上下颠倒 , 结果不同 , 不可以进行指令重排 ;
代码语言:javascript
复制
x = 0;
y = x;

② happens-before 规范 : 先行发生原则 ;

二、happens-before 先行发生原则


happens-before 先行发生原则 : A happens-before B , A 先于 B 发生 , 先 A 后 B ;

Java 虚拟机在编译时和运行时 , 会对 JVM 指令进行重排优化 , 很明显 , 指令重排会对线程并发产生影响 ;

为了保证并发编程的安全性 , 这里 规定了一些场景下 , 禁止在这些场景中 使用 指令重排 ;

happens-before 先行发生原则 适用场景 : 在以下场景中 , 不进行指令重排 , 这些先后顺序 , 绝对不能被打乱 , 否则会出现严重线程安全问题 ;

  • 程序次序原则 : 在程序内 , 按照代码书写的执行顺序 , 前面的代码先执行 , 后面的代码后执行 ; 时间上 靠前 的操作 先于 时间上靠后 的操作 执行 ;
  • 管程锁规则 : 不论是单线程还是多线程 , 线程 A 解锁后 , 线程 B 获取该锁 , 可以看到线程 A 的操作结果 ; 解锁的操作 先于 加锁的操作 ; 线程 B 要加锁 , 必须等待线程 A 解锁完毕才可以 ;
  • volatile 规则 : volatile 关键字修饰的变量 , 线程 A 对该变量的写操作 先于 线程 B 读取该变量的操作 , 线程 A 对该变量的写操作的结果对于线程 B 一定可见 ;
  • 线程启动规则 : 线程 start() 方法 先于 线程的具体执行的操作 ; 线程必须先启动 , 然后才能执行线程内的代码逻辑 ;
  • 线程终止规则 : 线程的具体操作 先于 线程的终止检测 ; 线程的代码逻辑执行完成 , 然后进行线程的终止检测 ;
  • 传递性 : happens-before 规则具有传递性 ; 如果 A happens-before B 和 B happens-before C , 则 A happens-before C ;
  • 线程中断 : 调用线程 interrupt() 方法 , 先于 被中断线程的代码 检测到 中断时 事件的发生 ; 必须先发生中断 , 然后才能被检测到 ; 不能还没发生中断 , 就可以检测到中断发生 ;
  • 对象终结 : 对象的创建 先于 对象的终结 , 创建就是调用构造函数 , 终结就是调用 finalize 方法 ;

只要符合上述规则 , 不需要进行同步 , 就可以成立 ;

通过 " happens-before 先行发生原则 " 可以判定两个线程的操作 , 是否有发生冲突的可能 ;

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-09-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 一、指令重排序规范
  • 二、happens-before 先行发生原则
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档