锁获取的内存可见性

时间:2013-06-22 22:38:17

标签: java concurrency

内存可见性取决于使用哪种显示器?锁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. 

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

2 个答案:

答案 0 :(得分:3)

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

  

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

您会看到,在那里指定了具体的监视器对象m。如果监视器不同,那么你就没有得到同步关系,因此,你不会在关系之前发生事情(从17.4.5开始):

  

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

因此,您的更新将在无序更新的情况下执行。

答案 1 :(得分:1)

内存可见性取决于使用哪种显示器?

锁A被释放后获得锁B,是否足以让内存可见?

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

阅读Java规范中Memory Model的优秀章节。