java.util.concurrent.atomic.LongAdder类的可行性

java.util.concurrent.atomic.LongAdder类的可行性,java,concurrency,atomic,java.util.concurrent,Java,Concurrency,Atomic,Java.util.concurrent,LongAdder是一种设计巧妙的原子计数器,它应该能够在更新共享计数器时减少缓存线争用。问题是,它依赖原子CAS操作来实际更新计数(这是它与更通用的longcummerator和friends共享的特性) 在amd64平台(可能还有其他平台)上,atomic CAS比atomic ADD慢得多,至少在涉及到中等数量的内核时是如此。因此,似乎在单个共享的VarHandle上简单地进行原子加法是一个更好的主意:代码更简单,而在一个通用(大约8个内核)容器上的性能也不差甚至更好 与VarHandle

LongAdder
是一种设计巧妙的原子计数器,它应该能够在更新共享计数器时减少缓存线争用。问题是,它依赖原子CAS操作来实际更新计数(这是它与更通用的
longcummerator
和friends共享的特性)

在amd64平台(可能还有其他平台)上,atomic CAS比atomic ADD慢得多,至少在涉及到中等数量的内核时是如此。因此,似乎在单个共享的
VarHandle
上简单地进行原子加法是一个更好的主意:代码更简单,而在一个通用(大约8个内核)容器上的性能也不差甚至更好

VarHandle
相比,使用
LongAdder
是否有任何好处

要了解更多上下文,请执行以下操作:

  • 默认情况下,Java将所有原子操作(甚至是简单的算术)作为CAS循环(例如:)来执行。然后,JIT可以自由地将内部函数升级到更好的东西,如果它愿意这样做的话
  • LongAdder
    ,作为一个分片CAS循环,肯定比任何简单的CAS循环都快,即使在低争用级别下也是如此
  • 然而,对于任何争用级别,“每个CPU一个CAS碎片”场景(
    LongAdder
    default)似乎都比AMD64上的实际硬件原子加法(“LOCK XADD”指令)慢一些。通过大量增加碎片的数量(至少2倍的CPU数量,在大倍数(如8倍或更高)的情况下可以实现额外的增益),可以加快速度
  • 不过,对一个合适的原子计数器(即进行硬件添加而不是CAS的计数器)进行简单的分片仍然会更快、更简单

  • LongAdder
    被设计为在写操作繁重的场景中比
    AtomicLong
    在任何级别的争用(除了无争用)都能更好地扩展,事实上它确实做到了

    如果您的场景不是写得很重,那么
    AtomicLong
    会更快

    C2编译器总是用硬编码程序集替换带注释的方法,而不仅仅是在感觉需要这样做的时候


    lock xadd
    比CAS重试循环更快地增加值
    LongAdder
    lock xadd
    快,因为它在线程之间分割计数器。它创建了多个计数器,因此减少了争用。

    LongAdder
    被设计为在除无争用之外的任何争用级别上,在写操作繁重的情况下都能比AtomicLong更好地扩展,事实上它确实做到了

    如果您的场景不是写得很重,那么
    AtomicLong
    会更快

    C2编译器总是用硬编码程序集替换带注释的方法,而不仅仅是在感觉需要这样做的时候


    lock xadd
    比CAS重试循环更快地增加值
    LongAdder
    lock xadd
    快,因为它在线程之间分割计数器。它创建了多个计数器,因此减少了争用。

    毫无疑问,
    LongAdder
    比简单的CAS循环快(正如您可能知道的,JVM默认情况下作为CAS执行所有原子操作,并且可能有选择地提升某些CAS使用以“锁定XADD”)。然而,在我看来,AMD64上的“LOCK XADD”总是比分片CA更快,无论争用级别如何。@oakad使用JMH基准来证明这一点是微不足道的。我在长加法器上观察到535M/s,在8核+8线程运行上观察到47M/s与XADD。毫无疑问,
    LongAdder
    比简单的CAS循环快(正如您可能知道的,JVM默认情况下作为CAS执行所有原子操作,并且可能有选择地促进某些CAS使用以“锁定XADD”)。然而,在我看来,AMD64上的“LOCK XADD”总是比分片CA更快,无论争用级别如何。@oakad使用JMH基准来证明这一点是微不足道的。我在LongAdder上观察到535M/s,在8核+8线程运行上观察到XADD的速度为47M/s。很可能你的基准测试有缺陷。请分享。你的基准可能有缺陷。请分享。