假设我有一个类的共享对象:
class Shared {
private int x = 0 ;
private int y = 0 ;
private Semaphore s = new Semaphore() ;
public int readX() {
s.p() ;
int x0 = x ;
s.v() ;
return x0 ; }
public void writeX(int x0) {
s.p() ;
x = x0 ;
s.v() ; }
public int readY() {
s.p() ;
int y0 = y ;
s.v() ;
return y0 ; }
public void writeY(int y0) {
s.p() ;
y = y0 ;
s.v() ; } }
这里的 Semaphore 是一个使用同步方法来提供互斥的类。
现在发生以下操作:
- 线程 0 调用 o.readX() 并发现它为 0。
- 线程 1 使用 o.writeX(1) 将 1 写入 x,然后将 1 写入 y; o.writeY(1) ;
- 线程 0 调用 o.readY() 获取 1,然后调用 o.readX()。
线程 0 能否从其缓存中读取并发现 x 为 0?为什么?
编辑
这是信号量类
class Semaphore {
private boolean available = true ;
public synchronized void v() {
available = true ; notifyAll() ; }
public synchronized void p() {
while( !available ) try{ wait() ; } catch(InterruptedException e){}
available = false ; }
}
最佳答案
根据 JMM,以下序列严格按照发生前关系排序,因此保证了在第 1 步中所做的更改对第 4 步的读者可见:
- 写信给x
- 退出由监视器 M 保护的同步块(synchronized block)
- 进入由监视器M保护的同步块(synchronized block)
- 读x
写入变量 happens-before 释放监视器,释放监视器 happens-before 获取相同的监视器和获取监视器 happens-before 从变量读取。
因此,如果 p
和 v
同步,则线程 0 将看到对 x 的更改。
关于java - 在 Java 中,锁定是否确保读取和写入非 volatile 位置的正确顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22069334/