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