JLS中说:
两个动作可以通过happens-before关系排序。如果一个动作发生在另一个动作之前,那么第一个动作对第二个动作可见并在第二个动作之前排序。
也有说:
例如,一个线程中的写入与另一个线程中的读取处于数据竞争中,这些读取可能会出现乱序。
这是否意味着 if ,hb(r, w)
thenr
一定在w
r
JLS中说:
两个动作可以通过happens-before关系排序。如果一个动作发生在另一个动作之前,那么第一个动作对第二个动作可见并在第二个动作之前排序。
也有说:
例如,一个线程中的写入与另一个线程中的读取处于数据竞争中,这些读取可能会出现乱序。
这是否意味着 if ,hb(r, w)
thenr
一定在w
r
hb(r, w)
表示在AND可以看到结果r
之前执行。w
w
r
在读/写操作的情况下,您通常关心有一个hb(w, r)
并希望确保读取看到写入的结果。
使用同步块的示例:
块w
(写入):
synchronized (lock) { //lock is a final object
aVariable = something;
}
块r
(读取):
synchronized (lock) { //the same final object
System.out.println(aVariable)
}
w
并且r
在同一个监视器上同步,因此两者之间存在发生之前的关系。
假设w
在 之前执行r
,这意味着我们有hb(w, r)
,那么 JMM 保证r
将打印 的最新值aVariable
。
如果没有同步块,就不再存在之前发生的关系,即使在w
之前执行r
(从挂钟的角度来看),r
也可能会打印aVariable
.
如果没有发生之前的关系,即使您的程序以不应该的方式编写(即 JVM 可能已重新排序操作) ,它甚至可能w
是在之后执行的情况。r
JLS - Example 17.4-1中给出了一个很好的例子,说明如果没有发生之前的关系,事情会变得多么奇怪。