Java 为什么FutureTask中的结果对象是非易变的?
我阅读了jsr166中的FutureTask类,发现结果对象是非易失性的,代码中的注释是“非易失性的,受状态读/写保护”第75行,状态是volatile int。我从中读取了Java内存模型,但没有找到准确的答案。有人知道原因吗?考虑一下这个计划:Java 为什么FutureTask中的结果对象是非易变的?,java,concurrency,lock-free,Java,Concurrency,Lock Free,我阅读了jsr166中的FutureTask类,发现结果对象是非易失性的,代码中的注释是“非易失性的,受状态读/写保护”第75行,状态是volatile int。我从中读取了Java内存模型,但没有找到准确的答案。有人知道原因吗?考虑一下这个计划: volatile int state; Integer result; void succeed(Integer result) if(state==PENDING) vr0 this.r
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;
如果volatile readvr2
看到DONE
,则表示它发生在volatile writevw1
之后。所以我们在关系之前就有了事件:w1->vw1->vr2->r2
。因此,writew1
对readr2
可见
但是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
之后执行volatile writestate=DONE
,以建立事件发生之前链
void succeed(Integer result)
if(state==PENDING) vr0
state=TMP; vw0
this.result = result; w1
state=DONE; vw1
还是在中科院
void succeed(Integer result)
if( compareAndSet(state, PENDING, TMP) ) vr0+vw0
this.result = result; w1
state=DONE; vw1