I read FutureTask class in jsr166, found that outcome object is non-volatile, the comments in code is "non-volatile, protected by state reads/writes" line 75, the state is volatile int. I have read Java Memory Model from Java Language Spec, but not found the accurate answer. Does anybody know the reason?
consider this program:
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;
If volatile read vr2 sees DONE, it means it happens after volatile write vw1. So we have happens-before relationships: w1 -> vw1 -> vr2 -> r2. Therefore write w1 is visible to read r2.
However succeed() isn't thread safe, since vr0 and vw1 are not atomic. If we use CAS
void succeed(Integer result)
if( compareAndSet(state, PENDING, DONE) ) vr0+vw0
this.result = result; w1
it fixes the atomicity issue. However, now w1 isn't necessarily visible to r2. The memory barrier effect of CAS is kind of like
void succeed(Integer result)
if(state==PENDING) vr0
state=DONE; vw0
this.result = result; w1
We have here vw0 -> vr2 -> r2, but w1 is not on the chain, there is no w1 -> r2
We must do the volatile write state=DONE after w1 to establish the happens-before chain.
void succeed(Integer result)
if(state==PENDING) vr0
state=TMP; vw0
this.result = result; w1
state=DONE; vw1
or in CAS
void succeed(Integer result)
if( compareAndSet(state, PENDING, TMP) ) vr0+vw0
this.result = result; w1
state=DONE; vw1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With