Java 8中AtomicLong类的CAS相关更改如何工作?

i_a*_*ero 5 java concurrency performance

在Java 8之前,AtomicLong类中CAS的代码是:

public final long incrementAndGet() {
    for (;;) {
        long current = get();
        long next = current + 1;
        if (compareAndSet(current, next))
          return next;
    }
}
Run Code Online (Sandbox Code Playgroud)

但现在它已被改为单一内在线:

public final long incrementAndGet() {
        return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L;
}
Run Code Online (Sandbox Code Playgroud)

这段代码比前者有什么优势?这个新代码如何工作?

Jim*_*son 6

原因是循环上的分支预测.在高争用情况下,CAS循环经常失败并且分支预测器开始预测执行路径将保持在循环中,当CAS最终成功时导致大量管道刷新.当你真正想要的是CAS失败时的退避,而不是加速时,这也会加速循环.

有关更详细的处理,请参阅https://blogs.oracle.com/dave/entry/atomic_fetch_and_add_vs.


apa*_*gin 5

unsafe.getAndAddLong是JVM内在的,由JIT转换为优化的指令序列.在x86上,它只是一个CPU指令LOCK XADD.