Java中happens-before的原则
本篇内容介绍了“Java中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。
“Java中happens-before的原则”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!