在JLS中说:
可以通过先发生关系来排序两个动作。如果一个动作发生在另一个动作之前,则第一个动作在第二个动作之前可见并且在第二个之前被命令。
也有说:
例如,在另一个线程中读取的数据争用中的一个线程中的写入可能看起来与这些读取无关。
这是否意味着如果hb(r, w)
,r
必须在w
之前,或如果 r
之前,那么 - 关系发生之前?
答案 0 :(得分:6)
hb(r, w)
表示在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
在同一台监视器上同步,因此2之间存在先发生关系。
假设w
在r
之前执行,意味着我们有hb(w, r)
,那么JMM保证r
将打印aVariable
的最新值}。
如果没有synchronized块,就不会再发生之前的关系,即使在w
之前执行r
(从挂钟的角度来看),r
可能会打印陈旧价值aVariable
。
如果没有发生在之前的关系,甚至可能是w
在r
之后执行的情况,即使你的程序以不应该是这种情况的方式编写(即JVM)可能已重新安排了这些操作。)
JLS - Example 17.4-1中给出了一个非常好的例子,说明如果没有发生在之前的关系,可以获得多么奇怪的事情。