Happens-beofre 先行发生原则(JVM 规范)

网友投稿 431 2022-05-30

如果JMM中所有的有序性都只靠volatile和synchronized,那么有一些操作将会变得很繁琐,但我们在编写Java并发代码时并没有感到这一点,这是因为Java语言中有一个先行发生(Happen-Before)原则

这个原则非常重要,它是判断数据是否存在竞争,线程是否安全的主要依赖。

Happens-beofre 先行发生原则(JVM 规范)

先行发生原则

指的是JMM中定义的两项操作之间的依序关系

happens- before关系 主要用于强调两个有冲突的动作之间的顺序,以及定义数据争用的发生时机

如果说操作A先行发生于操作B,就是在说发生B前,A产生的影响能被B观察到,“影响”包含了修改内存中共享变量的值、发送了消息、调用了方法等。意味着什么呢?如下例:

//线程A中执行 i = 1; //线程B中执行 j = i; //线程C中执行 i = 2;

1

2

3

4

5

6

7

8

下面是JMM下一些”天然的“先行发生关系,无须任何同步器协助就已经存在,可以在编码中直接使用

如果两个操作之间的关系不在此列,并且无法从下列规则推导出来的话,它们就没有顺序性保障,虚拟机可以对它们进行随意地重排序

具体的虚拟机实现,有必要确保以下

八大原则

程序次序规则(Pragram Order Rule)

在一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作。准确地说应该是控制流顺序而不是程序代码顺序,因为要考虑分支、循环结构。

对象锁(监视器锁)法则(Monitor Lock Rule )

某个 管程(也叫做对象锁,监视器锁) 上的unlock动作happens-before同一个管程上后续的lock动作 。这里必须强调的是同一个锁,而”后面“是指时间上的先后。

volatile变量规则(Volatile Variable Rule)

对某个volatile字段的写操作happens- before每个后续对该volatile字段的读操作,这里的”后面“同样指时间上的先后顺序。

线程启动规则(Thread Start Rule)

在某个线程对象 上调用start()方法happens- before该启动了的线程中的任意动作

线程终止规则(Thread Termination Rule)

某线程中的所有操作都先行发生于对此线程的终止检测,我们可以通过Thread.join()方法结束(任意其它线程成功从该线程对象上的join()中返回),Thread.isAlive()的返回值等作段检测到线程已经终止执行。

线程中断规则(Thread Interruption Rule)

对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生,可以通过Thread.interrupted()方法检测是否有中断发生

对象终结规则(Finalizer Rule)

一个对象初始化完成(构造方法执行完成)先行发生于它的finalize()方法的开始

传递性(Transitivity)

如果操作A先行发生于操作B,操作B先行发生于操作C,那就可以得出操作A先行发生于操作C的结论

一个操作”时间上的先发生“不代表这个操作会是”先行发生“,那如果一个操作”先行发生“是否就能推导出这个操作必定是”时间上的先发生“呢?也是不成立的,一个典型的例子就是指令重排序

所以时间上的先后顺序与先行发生原则之间基本没有什么关系,所以衡量并发安全问题一切必须以先行发生原则为准。

上面八条是原生Java满足Happens-before关系的规则,但是我们可以对他们进行推导出

其他满足happens-before的案例

将一个元素放入一个线程安全的队列的操作Happens-Before从队列中取出这个元素的操作

将一个元素放入一个线程安全容器的操作Happens-Before从容器中取出这个元素的操作

在CountDownLatch上的倒数操作Happens-Before CountDownLatch#await()操作

Semaphore:release许可的操作Happens-Before acquire许可 的操作

CyclicBarrier:线程中调用 await() 之前的操作 happen-before 那些是屏障操作的一部份的操作,后者依次 happen-before 紧跟在从另一个线程中对应 await() 成功返回的操作。

Future表示的任务的所有操作Happens-Before Future#get()操作

向Executor提交一个Runnable或Callable的操作Happens-Before任务开始执行操作

Java JVM 任务调度

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:【用户案例】世界人工智能大会的客服应该是怎样的?沃丰科技携手华为交答卷!
下一篇:用煲仔饭来说明IaaS/PaaS/SaaS的区别
相关文章