java - 为什么 FutureTask 中的结果对象是非 volatile 的?

标签 java concurrency lock-free

我读了jsr166中的FutureTask类,发现outcome对象是non-volatile的,代码中的注释是“non-volatile, protected by state reads/writes”第75行,state是volatile int。我已经从 Java Language Spec 阅读了 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 之后。所以我们有 happens-before 关系: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 之后执行 volatile 写入 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

关于java - 为什么 FutureTask 中的结果对象是非 volatile 的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14432400/

相关文章:

c++ - std::call_once 是免费的吗?

c++ - 无锁的原子函数改变两个独立的内存位置

java - 锁定与直接更新

java - 多处理器编程 : lock-free stacks

java - 在没有 Spring 的情况下注入(inject)应用程序属性

Java、IntelliJ、maven 项目 - 导入问题

Java 匹配循环

java - 函数和可运行对象同时工作(如何?)(Android、Java)

database - 如何处理 Web 应用程序中的并发更改?

java - Java并发中什么时候使用公平模式?