在 FutureTask 里面,普通写和 CAS 写是 混合使用的。比如
public boolean cancel(boolean mayInterruptIfRunning) {
if (!(state == NEW &&
UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
return false;
try { // in case call to interrupt throws exception
if (mayInterruptIfRunning) {
try {
Thread t = runner;
if (t != null)
t.interrupt();
} finally { // final state
UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED); //这里是普通写语义
}
}
} finally {
finishCompletion();
}
return true;
}
我这么解释对吗:
- 一来,这个状态转移是唯一的。INTERRUPTING 只能变成 INTERRUPTED 。其他线程暂时看不到 INTERRUPTED 也没关系。(注意,暂时看不到 INTERRUPTING,会导致 handlePossibleCancellationInterrupt 自旋)
- 二来。由于 finishCompletion 有其他的 CAS 操作,执行了 CAS 操作就相当于强制刷新了内存,所以只要 finishCompletion 执行了 CAS,那么其他线程也就能看到 INTERRUPTED 这个状态了。