2

内存可见性是否取决于使用的监视器?锁释放B后获取锁A,内存可见性够吗?

例如以下代码:

int state; // shared


// thread A
synchronized (A) {
 state += 1;
}
Thread.sleep(10000000);

// thread B
Thread.sleep(1000);
synchronized(B) {
 state += 1;
}

线程在同一时间启动,线程B休眠时间可以任意高,只是为了确保它在线程A使用state变量之后执行。线程A睡眠时间用于确保线程在线程B使用state共享变量之前不会完成。

更新

来自http://www.ibm.com/developerworks/library/j-jtp03304/

When a thread exits a synchronized block as part of releasing the associated monitor, the JMM requires that the local processor cache be flushed to main memory.

Similarly, as part of acquiring the monitor when entering a synchronized block, local caches are invalidated so that subsequent reads will go directly to main memory and not the local cache.

如果这是真的,那么我看不出state变量对线程不可见的原因B

此外,他们说监视器应该是相同的,但上述陈述并未暗示。

This process guarantees that when a variable is written by one thread during a synchronized block protected by a given monitor and read by another thread during a synchronized block protected by the same monitor, the write to the variable will be visible by the reading thread. 

似乎本地内存刷新的过程并不像第一条语句中描述的那么简单,并且可能不会在每次锁定释放时发生?

4

2 回答 2

3

是的,这取决于。你可以阅读这个文档。相关部分是“17.4.4.同步顺序”:

监视器 m 上的解锁操作与 m 上的所有后续锁定操作同步(其中“后续”根据同步顺序定义)。

你看,那里指定了一个具体的监视器对象m。如果监视器不同,那么您不会获得 synchronizes-with 关系,因此,您不会获得happens-before 关系(来自 17.4.5):

如果动作 x 与后续动作 y 同步,那么我们也有 hb(x, y)。

因此,您的更新将无序执行,可能会丢失更新。

于 2013-06-22T22:50:17.000 回答
1

内存可见性是否取决于使用的监视器?是的。

锁A释放后获取锁B,内存可见性够吗?不。

两个线程必须在同一个监视器上同步才能看到彼此的写入。在您的示例中,两个线程都可以看到state具有 value 1。无论您插入什么睡眠间隔。当然,这取决于您使用的 JVM 的实现,不同的 JVM 可能会产生不同的结果。基本上,您对字段的访问是不同步的,应该始终避免这种情况(因为它的值不是确定性的state)。

在 Java 规范中关于内存模型的优秀章节中阅读更多内容。

于 2013-06-22T23:03:58.687 回答