在Java 8之前,AtomicLong类中的CAS代码是:
public final long incrementAndGet() {
for (;;) {
long current = get();
long next = current + 1;
if (compareAndSet(current, next))
return next;
}
}
但是现在它已更改为单个内在行:
public final long incrementAndGet() {
return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L;
}
此代码相对于前者有什么优势?这个新代码如何工作?
最佳答案
原因是循环上的分支预测。在争用较高的情况下,CAS循环经常失败,分支预测器开始预测执行路径将停留在循环中,从而在CAS最终成功时导致大量流水线刷新。当您真正想要的是CAS失败时的退避(而不是加速)时,这也会加快循环。
有关更多详细信息,请参见https://blogs.oracle.com/dave/entry/atomic_fetch_and_add_vs。