【问题标题】:How CAS related changes in AtomicLong class in Java 8 work?Java 8 中 AtomicLong 类中与 CAS 相关的更改如何工作?
【发布时间】:2015-03-25 06:39:01
【问题描述】:

在 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;
}

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

【问题讨论】:

    标签: java performance concurrency


    【解决方案1】:

    原因是循环上的分支预测。在高竞争下,CAS 循环经常失败,分支预测器开始预测执行路径将停留在循环中,当 CAS 最终成功时会导致大量管道刷新。当您真正想要的是 CAS 失败时的回退而不是加速时,这也会加快循环速度。

    查看https://blogs.oracle.com/dave/entry/atomic_fetch_and_add_vs了解更详细的处理方法。

    【讨论】:

      【解决方案2】:

      unsafe.getAndAddLong 是 JVM 内在函数,由 JIT 翻译成优化的指令序列。在 x86 上,它只是一条 CPU 指令LOCK XADD

      【讨论】:

        【解决方案3】:

        正如 Jim 提供的链接中所讨论的,在 Java 8 中 incrementAndGet 和其他方法正在利用硬件对“锁定、获取和添加”指令的支持。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-06-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-10-01
          • 1970-01-01
          相关资源
          最近更新 更多