我读了jsr166中的FutureTask类,发现结果对象是非易失性的,代码中的注释是"non- volatile,protected by state read /writes“第75行,状态是volatile。我已经阅读了Java Language Spec的Java Memory Model,但没有找到准确的答案。有人知道原因吗?
发布于 2013-01-21 13:30:07
考虑这个程序:
volatile int state;
Integer result;
void succeed(Integer result)
if(state==PENDING) vr0
this.result = result; w1
state = DONE; vw1
Integer peekResult()
if(state==DONE) vr2
return result; r2
return null;如果易失性读vr2看到DONE,这意味着它发生在易失性写vw1之后。所以我们有发生在关系之前的事情:w1 -> vw1 -> vr2 -> r2。因此,对于读取r2,写入w1是可见的。
然而,succeed()不是线程安全的,因为vr0和vw1不是原子的。如果我们使用CAS
void succeed(Integer result)
if( compareAndSet(state, PENDING, DONE) ) vr0+vw0
this.result = result; w1它修复了原子性问题。然而,现在w1对r2不一定是可见的。CAS的记忆屏障效应类似于
void succeed(Integer result)
if(state==PENDING) vr0
state=DONE; vw0
this.result = result; w1我们这里有vw0 -> vr2 -> r2,但w1不在链上,没有w1 -> r2
我们必须在w1之后执行易失性写入state=DONE来建立发生之前的链。
void succeed(Integer result)
if(state==PENDING) vr0
state=TMP; vw0
this.result = result; w1
state=DONE; vw1或在CAS中
void succeed(Integer result)
if( compareAndSet(state, PENDING, TMP) ) vr0+vw0
this.result = result; w1
state=DONE; vw1https://stackoverflow.com/questions/14432400
复制相似问题