为什么FutureTask中的结果对象是非易失性的



我在jsr166中阅读FutureTask类,发现结果对象是非易失性的,代码中的注释是"非易失性,受状态读/写保护"第75行,状态是易失性int。我从Java语言规范中阅读了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;

如果易失性读vr2看到DONE,则表示它发生在易失性写vw1之后。所以我们有发生前的关系:w1 -> vw1 -> vr2 -> r2。因此,写w1对读r2是可见的。

然而succeed()不是线程安全的,因为vr0vw1不是原子的。如果我们使用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,以建立happens-before链。

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

最新更新