如果JMM中所有的有序性都只靠volatile和synchronized,那么有一些操作将会变得很繁琐,但我们在编写Java并发代码时并没有感到这一点,这是因为Java语言中有一个先行发生(Happen-Before)
原则
这个原则非常重要,它是判断数据是否存在竞争,线程是否安全的主要依赖。
指的是JMM中定义的两项操作之间的依序关系
happens- before关系
主要用于强调两个有冲突的动作之间的顺序,以及定义数据争用的发生时机
如果说操作A先行发生于操作B,就是在说发生B前,A产生的影响能被B观察到,“影响”包含了修改内存中共享变量的值、发送了消息、调用了方法等。意味着什么呢?如下例:
//线程A中执行
i = 1;
//线程B中执行
j = i;
//线程C中执行
i = 2;
下面是JMM下一些”天然的“先行发生关系,无须任何同步器协助就已经存在,可以在编码中直接使用 如果两个操作之间的关系不在此列,并且无法从下列规则推导出来的话,它们就没有顺序性保障,虚拟机可以对它们进行随意地重排序
具体的虚拟机实现
,有必要确保以下
一个操作”时间上的先发生“不代表这个操作会是”先行发生“,那如果一个操作”先行发生“是否就能推导出这个操作必定是”时间上的先发生“呢?也是不成立的,一个典型的例子就是指令重排序 所以时间上的先后顺序与先行发生原则之间基本没有什么关系,所以衡量并发安全问题一切必须以先行发生原则为准。
上面八条是原生Java满足Happens-before关系的规则,但是我们可以对他们进行推导出