关于Java发生之前的关系,需要澄清

时间:2012-07-13 11:04:00

标签: java multithreading

JLS中说:

  

可以通过先发生关系来排序两个动作。如果一个动作发生在另一个动作之前,则第一个动作在第二个动作之前可见并且在第二个之前被命令。

也有说:

  

例如,在另一个线程中读取的数据争用中的一个线程中的写入可能看起来与这些读取无关。

这是否意味着如果hb(r, w)r必须在w之前,或如果 r之前,那么 - 关系发生之前?

1 个答案:

答案 0 :(得分:6)

hb(r, w)表示在r之前执行ww可以看到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)
}

wr在同一台监视器上同步,因此2之间存在先发生关系。

假设wr之前执行,意味着我们有hb(w, r),那么JMM保证r将打印aVariable的最新值}。

如果没有synchronized块,就不会再发生之前的关系,即使在w之前执行r(从挂钟的角度来看),r可能会打印陈旧价值aVariable

如果没有发生在之前的关系,甚至可能是wr之后执行的情况,即使你的程序以不应该是这种情况的方式编写(即JVM)可能已重新安排了这些操作。)

JLS - Example 17.4-1中给出了一个非常好的例子,说明如果没有发生在之前的关系,可以获得多么奇怪的事情。