8
我在jsr166中读取FutureTask类,发现结果对象是非易失性的,代码中的注释是“非易失性的,受状态读/写保护”第75行,状态是volatile int。我已经从Java Language Spec阅读Java内存模型,但没有找到准确的答案。有人知道原因吗?为什么FutureTask中的结果对象是非易失性的?
我在jsr166中读取FutureTask类,发现结果对象是非易失性的,代码中的注释是“非易失性的,受状态读/写保护”第75行,状态是volatile int。我已经从Java Language Spec阅读Java内存模型,但没有找到准确的答案。有人知道原因吗?为什么FutureTask中的结果对象是非易失性的?
考虑此程序:
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
。因此编写w1
是可见的阅读r2
。
但是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; vw1
非常有用的答案,更清楚地理解 – taigetco