使用“UNSAFE.putOrderedInt(this,stateOffset,NORMAL);“
在FutureTask类中,设置结果值的方法是
protected void set(V v) {
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = v;
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
finishCompletion();
}
}
我对UNSAFE.putOrderedInt(this, stateOffset, NORMAL);
感到困惑,为什么不直接改变状态,就像这个state = NORMARL
,并使用putOrderedInt
方法修改值对其他线程不可见。我不明白使用UNSAFE.putOrderedInt(this, stateOffset, NORMAL);
的好处是什么
1条答案
按热度按时间kqqjbcuj1#
好处是性能。
“state = NORMAL”导致易失性存储,因为“state”是易失性变量。putOrderInt是一个发布存储区。在现代的JDK中,你会看到一个'STATE.setRelease(this,NORMAL);易失性存储通常比释放存储昂贵得多,因为它具有更严格的存储器排序保证。
在X86上,易失性存储之后通常是[StoreLoad]围栏,这使得后续加载等待直到存储缓冲区耗尽。并且这可能需要时间,因为一旦其他CPU上该高速缓存行已经无效,CPU就只能将存储提交到一致性高速缓存。在X86上,每个存储都是一个发布存储,因此不需要任何内存围栏(主要目的是控制JIT)。因此,CPU每单位时间可以执行更多的指令。
注意:Java中正确同步的程序只能有顺序一致的执行。对于顺序一致性,实时顺序是不相关的。因此,从“立即可见”的Angular 来讨论没有多大意义,因为Java内存模型并不需要它。如果实时顺序是相关的,那么您需要查看线性化(这不是JMM的一部分)。与释放存储相比,易失性存储不会使该存储对其他CPU可见得更快;存储缓冲器已经被尽可能快地耗尽。