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

举报
JavaEdge 发表于 2021/06/04 01:10:51 2021/06/04
【摘要】 如果JMM中所有的有序性都只靠volatile和synchronized,那么有一些操作将会变得很繁琐,但我们在编写Java并发代码时并没有感到这一点,这是因为Java语言中有一个先行发生(Happen-Before)原则 这个原则非常重要,它是判断数据是否存在竞争,线程是否安全的主要依赖。 先行发生原则 指的是JMM中定义的两项操作之间的依序关系 happen...

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

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

先行发生原则

指的是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任务开始执行操作

文章来源: javaedge.blog.csdn.net,作者:JavaEdge.,版权归原作者所有,如需转载,请联系作者。

原文链接:javaedge.blog.csdn.net/article/details/106450450

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。