我在 jsr166 中阅读 FutureTask 类,发现结果对象是非易失性的,代码中的注释是“非易失性,受状态读/写保护”第 75 行,状态是 volatile int。我从Java Language Spec阅读了 Java Memory Model ,但没有找到准确的答案。有人知道原因吗?
1 回答
            7        
        
		
考虑这个程序:
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如果看到volatile read DONE,则表示它发生在 volatile write 之后vw1。所以我们有发生之前的关系:   w1 -> vw1 -> vr2 -> r2. 因此 writew1对 read 可见r2。
但是succeed()不是线程安全的,因为vr0并且vw1不是原子的。如果我们使用 CAS
void succeed(Integer result)
    if( compareAndSet(state, PENDING, DONE) )      vr0+vw0
        this.result = result;                       w1
它解决了原子性问题。但是, noww1不一定对r2. CAS的记忆屏障效应有点像
void succeed(Integer result)
    if(state==PENDING)         vr0
        state=DONE;            vw0
        this.result = result;   w1
我们这里有vw0 -> vr2 -> r2,但w1不在链上,没有w1 -> r2
我们必须执行 volatile write state=DONEafterw1以建立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
于 2013-01-21T05:30:06.753   回答