Java 先行发生原则(Happens

编程入门 行业动态 更新时间:2024-10-28 04:22:22

Java 先行发生<a href=https://www.elefans.com/category/jswz/34/1769377.html style=原则(Happens"/>

Java 先行发生原则(Happens

读《深入理解Java虚拟机》第三版,周志明著。
读《Java并发编程的艺术》方腾飞、魏鹏、程晓明著。
读《Java并发编程实战》。
笔记。

先行发生原则可以判断数据是否存在竞争,线程是否安全。
如果两个操作之间缺乏 happens-before关系,那么 JVM 可以对它们任意地排序。

一、什么是 “ 先行发生 ” ?

先行发生是 Java 内存模型中定义的两项操作之间的偏序关系,比如说操作 A 先行发生于操作 B,其实就是说在发生操作 B 之前,操作 A产生的影响能被操作 B观察到,“ 影响 ” 包括修改了内存中共享变量的值、发送了消息、调用了方法等。

《JSR-133: Java Memory Model and Thread Specification》对 happens-before 关系的定义如下:

  • 如果一个操作 happens-before 另一个操作,那么第一个操作的执行结果将被第二个操作可见,而且第一个操作的执行顺序排在第二个操作之前。
  • 两个操作之间存在 happens-before 关系,并不意味着 Java 平台的具体实现必须要按照 happens-before 关系指定的顺序来执行。如果重排序之后的执行结果,与按 happens-before 关系来执行的结果一致,那么这种重排序并不非法(也就是说,JMM允许这种重排序)。

第一条是JMM对程序的承诺。从程序员的角度来说,可以这样理解 happens-before 关系:如果 A happens-before B,那么Java内存模型将向程序员保证——A操作的结果将对B可见,且A的执行顺序排在B之前。注意这只是Java内存模型向程序员做出的保证!
第二条是JMM对编译器和处理器重排序的约束原则。正如前面所言,JMM其实是在遵循一个基本原则:只要不改变程序的执行结果(指的是单线程程序和正确同步的多线程程序),编译器和处理器怎么优化都行。JMM这么做的原因是:程序员对于这两个操作是否真的被重排序并不关心,程序员关心的是程序执行时的语义不能被改变(即执行结果不能被改变)。

二、一些 “ 天然的 ” 先行发生关系

这些先行发生关系无须任何同步器协助就已经存在,可以在编码中直接使用。

  • 程序次序规则(Program Order Rule):在一个线程内,按照控制流顺序,书写在签名的操作先行发生于书写在后面的操作。注意,这里说的是控制流顺序而不是程序代码顺序,因为要考虑分支、循环等结构。
  • 管程锁定规则(Monitor Lock Rule):在一个 unlock 操作先行发生于后面对同一个锁的 lock 操作。这里的 “ 后面 ” 是指时间上的先后
  • volatile 变量规则(Volatile Variable Rule):对一个 volatile 变量写操作先行发生于后面对这个变量的读操作,这里的 “ 后面 ” 同样是指时间上的先后
  • 线程启动规则(Thread Start Rule):Thread 对象的 start() 方法先行发生于此线程的每个动作。
  • 线程终止规则(Thread Termination Rule):线程中的所有操作都先行发生于对此线程的终止检测,我们可以通过 Thread::join() 方法是否结束Thread::isAlive() 的放回值等手段检测线程是否已经终止执行。
  • 线程中断规则(Thread Interruption Rule):对线程 interrupt() 方法的调用先行发生于被中断线程的代码检测到中断事件的发生,可以通过 Thread::interrupted() 方法检测到是否有中断发生。
  • 对象终结规则(Finalizer Rule):一个对象的初始化完成(构造函数执行结束)先行发生于它的 finalize() 方法的开始。
  • 传递性(Transitivity):如果操作 A 发行发生于操作 B操作 B 先行发生于操作 C ,那就可以得出操作 A 先行发生于操作 C 的结论。

三、换个角度理解 happens-before 规则

  • 程序顺序规则:一个线程中的每个操作,happens-before 于该线程中的任意后续操作。
  • 监视器规则:对一个锁的解锁,happens-before 于随后对这个锁的加锁。
  • volatile 变量规则:对一个 volatile 域的写,happens-before 于任意后续对这个 volatile 域的读。
  • 传递性:如果 A happens-before B,且 B happens-before C,那么 A happens-before C。

更多推荐

Java 先行发生原则(Happens

本文发布于:2024-03-06 18:24:34,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1716044.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:原则   发生   Java

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!