【问题标题】:How LongAdder performs better than AtomicLongLongAdder 如何比 AtomicLong 表现更好
【发布时间】:2015-08-21 20:28:51
【问题描述】:

我看到了 Java 的 AtomicInteger 如何在内部与 CAS(比较和交换)操作一起工作。基本上当多个线程尝试更新值时,JVM 内部会使用底层的 CAS 机制并尝试更新值。如果更新失败,则使用新值重试,但永远不会阻塞。

在 Java8 中,Oracle 引入了一个新的类 LongAdder,它在高竞争下似乎比 AtomicInteger 表现更好。一些博客文章声称 LongAdder 通过维护内部单元格表现更好 - 这是否意味着 LongAdder 在内部聚合值并稍后更新?您能帮我了解一下 LongAdder 的工作原理吗?

【问题讨论】:

  • 起初我想我误解了你。再次阅读您的问题,我认为您的想法是正确的。
  • 谢谢!我更感兴趣的是了解这些内部细胞是如何组织的?假设有 100 个线程试图更新值,创建了多少个内部单元格以及它们是如何更新的?
  • 关于实现细节的此类问题,我建议您参考来源。它实际上很容易阅读和理解。请参阅我的更新答案以获取最新版本的链接。

标签: java concurrency


【解决方案1】:

这是否意味着 LongAdder 会在内部聚合值并稍后更新?

是的,如果我理解正确的话。

LongAdder 中的每个Cell 都是AtomicLong 的变体。拥有多个这样的单元是分散争用从而提高吞吐量的一种方式。

当要检索最终结果(总和)时,它只是将每个单元格的值相加。

关于单元格如何组织、如何分配等的大部分逻辑都可以在源代码中看到:http://hg.openjdk.java.net/jdk9/jdk9/jdk/file/f398670f3da7/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java

尤其是单元的数量受 CPU 数量的限制:

/** Number of CPUS, to place bound on table size */
static final int NCPU = Runtime.getRuntime().availableProcessors();

【讨论】:

    【解决方案2】:

    它“更快”的主要原因是它的竞争性能。这很重要,因为:

    在低更新竞争下,这两个类具有相似的特征。

    您将使用 LongAdder 进行非常频繁的更新,其中 原子 CAS 和对 Unsafe 的本机调用会导致争用。 (见sourcevolatile reads)。更不用说多个 AtomicLongs 上的 cache misses/false sharing(虽然我还没有查看类布局,但在实际的 long 字段之前似乎没有足够的内存填充。

    在高争用情况下,该类的预期吞吐量明显更高,但代价是更高的空间消耗。

    实现扩展 Striped64,它是 64 位值的数据持有者。这些值保存在填充(或条纹)的单元格中,因此得名。在 LongAdder 上进行的每个操作都会修改 Striped64 中存在的值集合。当发生争用时,会创建和修改一个新的单元格,因此旧线程可以与竞争一个同时完成。当您需要最终值时,只需将每个单元格的总和相加即可。

    不幸的是,性能是有代价的,在这种情况下是内存(通常是这样)。如果大量线程和更新被抛出,Striped64 可能会变得非常大。

    引用来源: Javadoc for LongAdder

    【讨论】:

      【解决方案3】:

      Atomic Long 使用 CAS,在激烈的争用下会导致许多 CPU 周期的浪费。 另一方面,LongAdder 使用了一个非常聪明的技巧来减少线程之间的争用,当这些线程增加它时。 因此,当我们调用 increment() 时,LongAdder 在幕后维护了一个可以按需增长的计数器数组。 因此,当更多线程调用 increment() 时,数组会更长。数组中的每条记录都可以单独更新——减少争用。由于这个事实,LongAdder 是一种从多个线程递增计数器的非常有效的方法。 在调用sum() 方法之前,LongAdder 中的计数器的结果是不可用的。

      【讨论】:

        猜你喜欢
        • 2016-06-11
        • 2021-04-20
        • 1970-01-01
        • 2011-07-07
        • 2012-08-03
        • 1970-01-01
        • 1970-01-01
        • 2011-09-28
        • 1970-01-01
        相关资源
        最近更新 更多