首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么FutureTask中的结果对象是非易失性的?

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

Stack Overflow用户
提问于 2013-01-21 12:08:50
回答 1查看 466关注 0票数 8

我读了jsr166中的FutureTask类,发现结果对象是非易失性的,代码中的注释是"non- volatile,protected by state read /writes“第75行,状态是volatile。我已经阅读了Java Language Spec的Java Memory Model,但没有找到准确的答案。有人知道原因吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-01-21 13:30:07

考虑这个程序:

代码语言:javascript
复制
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()不是线程安全的,因为vr0vw1不是原子的。如果我们使用CAS

代码语言:javascript
复制
void succeed(Integer result)
    if( compareAndSet(state, PENDING, DONE) )      vr0+vw0
        this.result = result;                       w1

它修复了原子性问题。然而,现在w1r2不一定是可见的。CAS的记忆屏障效应类似于

代码语言:javascript
复制
void succeed(Integer result)
    if(state==PENDING)         vr0
        state=DONE;            vw0
        this.result = result;   w1

我们这里有vw0 -> vr2 -> r2,但w1不在链上,没有w1 -> r2

我们必须在w1之后执行易失性写入state=DONE来建立发生之前的链。

代码语言:javascript
复制
void succeed(Integer result)
    if(state==PENDING)            vr0
        state=TMP;                vw0
        this.result = result;      w1
        state=DONE;               vw1

或在CAS中

代码语言:javascript
复制
void succeed(Integer result)
    if( compareAndSet(state, PENDING, TMP) )       vr0+vw0
        this.result = result;                       w1
        state=DONE;                                vw1
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14432400

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档