Java多线程 - Happens-Before 规则

总结

Java 为了让大家理解JMM(java memory model, java内存模型)中“内存可见性”的这个概念,􏰀提出了 happens-before 的概念。

1
2
3
如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须要存在 happens-before 关系
 
两个操作之间具有 happens-before 关系,并不意味着前一个操作必须要在后 一个操作之前执行!happens-before 仅仅要求前一个操作(执行的结果)对后一个操作可见

 

1)站在 Java 程序员的角度来说: JMM 保证,如果一个操作 happens-before 另一个操作,那么第一个操作的执行结果将对第二个操作可见,而且第一个操作 的执行顺序排在第二个操作之前。

2)站在编译器和处理器的角度来说: JMM 允许,两个操作之间存在 happens-before 关系,不要求 Java 平台的具体实现必须要按照 happens-before 关系指定的顺序来执行。如果重排序之后的执行结果,与按 happens-before 关系 来执行的结果一致,那么这种重排序是允许的。

 

例子

page126image14243104
 

站在我们 Java 程序员的角度有三个依赖关系:

page126image14242896

 

但是仔细考察,2、3 是必需的,而 1 并不是必需的,因此 JMM 对这三个 happens-before 关系的处理就分为两类:

  1. 会改变程序执行结果的重排序 (在这里指的是,依赖关系2+3)
  2. 不会改变程序执行结果的重排序(在这里指的是,依赖关系1)

JMM 对这两种不同性质的重排序,采用了不同的策略,如下:

  1. 对于会改变程序执行结果的重排序,JMM 要求编译器和处理器必须禁止这 种重排序;
  2. 对于不会改变程序执行结果的重排序,JMM 对编译器和处理器不做要求。

于是,站在我们程序员的角度,看起来这个三个操作满足了 happens-before 关系,而站在编译器和处理器的角度,进行了重排序,而排序后的执行结果,也 是满足 happens-before 关系的。

 

happens-before 关系本质上和 as-if-serial 语义是一回事:

  • as-if-serial 语义保证单线程内程序的执行结果不被改变
  • happens-before 关系保证正确同步的多线程程序 的执行结果不被改变

 

Happens-Before 规则

  • 程序次序规则:在一个线程内,按照程序控制流顺序,书写在前面的操作先行发生于书写在后面的操作
  • 管程锁定规则:一个unlock操作先行发生于后面对同一个锁的lock操作
  • volatile变量规则:对一个volatile变量的写操作,先行发生于后面对这个变量的读操作
  • 线程启动规则:Thread对象的start()方法先行发生于此线程的每一个动作
  • 线程终止规则:线程中的所有操作都先行发生于对此线程的终止检测
  • 线程中断规则:对线程interrupt()方法的调用,先行发生于被中断线程的代码检测到中断事件的发生
  • 对象终结规则:一个对象的初始化完成(构造函数执行结束)先行发生于它的finalize()方法的开始
 

posted on   frank_cui  阅读(384)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

levels of contents
点击右上角即可分享
微信分享提示