APP下载

happens-before原则

消息来源:baojiabao.com 作者: 发布时间:2024-05-16

报价宝综合消息happens-before原则

在Java中有一个很重要的原则,这个原则是判断执行绪是否存在资料竞争、执行绪是否安全的主要依据,这个原则就是happens-before原则。我们首先看一下到底什么是happens-before原则。简单来说happens-before原则就是JMM中定义的两项操作之间的偏向关系。假如我们有两个操作A和B。如果A操作先行发生于B操作,也就是A操作在B操作之前发生,那么在A操作在发生之后产生的影响B操作可以获取到,这里所说的影响主要包括修改共享变数、呼叫方法等。上述就是happens-before原则的定义,下面我们用一个简单的例子来说明一下happens-before原则到底有什么作用。

我们假设上述程式码中的3条语句分别由3个执行绪执行,并假如这3个执行绪分别是thread-1、thread-2、thread-3。如果我们指定thread-1要优先于thread-2执行那么我们就会得出结论thread-2在执行完成后,变数j的值一定是1。原因就是根据happens-before原则,thread-1先行发生于thread-2,所以thread-1执行后的值,thread-2是可以获取到的,并且我们假设thread-3没有执行。那么在thread-1执行后,变数i的值没有被其它执行绪修改过,所以thread-2在获取变数i时值为1。下面我们假设thread-1和thread-2还具有happens-before关系,也就是说thread-1在thread-2之前执行并且我们假设thread-2和thread-3并没有happens-before关系。也就是说thread-2和thread-3谁先执行并不是确定的。如果thread-3在thread-2之前执行的,那么thread-2中变数j的值是多少呢?答案可想而知,变数j的值是不确定的。因为我们并不确定thread-1和thread-3到底谁先执行。如果thread-3比thread-1先执行,那么因为thread-1和thread-2有happens-before关系,所以并不会对变数j的值产生影响,但如果thread-1比thread-3先执行,那么thread-2在获取变数i的值时,就是有可能获取到过期的资料了,这就造成的所谓的执行绪安全问题了。

在JMM中直接就具有happens-before原则,我们不需要进行任何同步,可以直接在编码中使用它们。如果程式码中的操作没有happens-before原则的话,那么虚拟机器在执行的时候,就有可能对它们进行随意的重排序。下面我们看一下在JMM中都有哪些操作是预设具有happens-before原则的。

程式次序规则:在一个执行绪内,按照程式程式码顺序,写在前面的程式码先行发生于写在后面的程式码。(暂时不考虑分支判断、循环等)管程锁定规则:一个unlock操作先行发生于后面对同一个锁的lock操作。volatile变数规则:对一个volatile变数的写操作先行发生于后面对这个变数的读操作。执行绪启动规则:Thread物件的start()方法先行发生于此执行绪的每一个动作。执行绪终止规则:执行绪中的所有操作都先行发生于对此执行绪的终止检测。物件终结规则:一个物件的初始化先行发生于它的finalize()方法。传递性:如果操作A先行发生于操作B,操作B先行发生于操作C,那操作也A先行发生于操作C。

2019-07-18 12:56:00

相关文章