JMM之happens-before原则

  下面是Java内存模型下一些“天然的”先行发生关系, 这些先行发生关系无须任何同步器协助就已经存在, 可以在编码中直接使用。 如果两个操作之间的关系不在此列, 并且无法从下列规则推导出
来, 则它们就没有顺序性保障, 虚拟机可以对它们随意地进行重排序。

  在Java内存模型中,happens-before 应该翻译成:前一个操作的结果可以被后续的操作获取。讲白点就是前面一个操作把变量a赋值为1,那后面一个操作肯定能知道a已经变成了1。为了解决多线程的可见性问题,就搞出了happens-before原则,让线程之间遵守这些原则。编译器还会优化我们的语句,所以等于是给了编译器优化的约束。

  
1 程序次序规则( Program Order Rule):在一个线程内,按照控制流顺序, 书写在前面的操作先行发生于书写在后面的操作。 注意, 这里说的是控制流顺序而不是程序代码顺序, 因为要考虑分支、 循环等结构。在一个线程内一段代码的执行结果是有序的。就是还会指令重排,但是随便它怎么排,结果是按照我们代码的顺序生成的不会变!

2 管程锁定规则( Monitor Lock Rule) : 对于同一个锁来说,一个线程对这个锁解锁之后,另一个线程获取了这个锁都能看到前一个线程的操作结果!


3 volatile变量规则( Volatile Variable Rule):一个线程先去写一个volatile变量,然后一个线程去读这个变量,那么这个写操作的结果一定对读的这个线程可见。


4 线程启动规则( Thread Start Rule):在主线程A执行过程中,启动子线程B,那么线程A在启动子线程B之前对共享变量的修改结果对线程B可见。


5 线程终止规则( Thread Termination Rule) : 在主线程A执行过程中,子线程B终止,那么线程B在终止之前对共享变量的修改结果在线程A中可见。


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


7 对象终结规则( Finalizer Rule) : 一个对象的初始化完成( 构造函数执行结束) 先行发生于它的
finalize()方法的开始。


8 传递性( Transitivity) : 如果操作A先行发生于操作B, 操作B先行发生于操作C, 那就可以得出
操作A先行发生于操作C的结论。



原文地址:https://www.cnblogs.com/juniorMa/p/14287332.html