高并发编程-happens-before
477
2022-05-30
如果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任务开始执行操作
Java JVM 任务调度
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。