Java 为什么FutureTask中的结果对象是非易变的?

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

我阅读了jsr166中的FutureTask类,发现结果对象是非易失性的,代码中的注释是“非易失性的,受状态读/写保护”第75行,状态是volatile int。我从中读取了Java内存模型,但没有找到准确的答案。有人知道原因吗?

考虑一下这个计划:

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 read
vr2
看到
DONE
,则表示它发生在volatile write
vw1
之后。所以我们在关系之前就有了事件:
w1->vw1->vr2->r2
。因此,write
w1
对read
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
之后执行volatile write
state=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