假设我有一个类的共享对象:
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() ; } }
此处信号量是一个使用 synchronized 方法提供互斥的类。
现在发生以下行动:
线程0是否可以从其缓存读取并发现x为0?为什么呢?
修改
这是Semaphore类
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 ; }
}
答案 0 :(得分:3)
根据JMM,以下序列严格按先发条件关系排序,因此保证在步骤4中步骤1中对读者所做的更改的可见性:
写入变量发生 - 在释放监视器之前,释放监视器 - 在获取同一监视器并获取监视器之前 - 在从变量读取之前发生。
因此,如果同步p
和v
,则线程0将看到对x的更改。
答案 1 :(得分:3)
并排显示两个主题的动作:
Thread 1 Thread 2 o.readX(); // 0 o.writeX(1); o.readY(); // 1 o.writeY(1); o.readX(); // must be 1
对Semaphore
方法的任意选择的调用对进行严格的发生 - 排序,因为它们都在同一个共享{{1}上进行获取 - 释放循环实例。
我们有:
Semaphore
发生在之前 o.writeX(1)
; o.writeY(1)
由线程2 在线程1之前发生 o.writeY(1)
; o.readY() -> 1
之前由线程1发生o.readY()
; o.readX()
; o.writeX(1)
的结果必须为1.