【问题标题】:Using LongAdder in Java在 Java 中使用 LongAdder
【发布时间】:2021-05-29 14:29:18
【问题描述】:

我正在阅读 Cay S. Horstmann 撰写的《Core Java I》一书,他在第 580 页提到了 LongAdder

如果您预计会出现高争用 [*1],您应该简单地使用 LongAdder 而不是 原子长。方法名称略有不同。调用 increment 来增加一个计数器 或 add 以添加数量,然后求和以检索总数。

var adder = new LongAdder();
for (. . .)
  pool.submit(() -> {
    while (. . .) {
       . . .
       if (. . .) adder.increment();
    }
});
. . .
long total = adder.sum();

注意 当然,增量方法不会返回旧的 [*2] 值。这样做会撤消 将总和拆分为多个和的效率增益。

在 [*1] 中的“争用”一词,我认为他的意思是机器的第二个严重过载,即有很多线程在运行 java 代码。

在 [*2] 中,他提到了 old 值。 oldnew 在这种情况下的价值是什么?能否请您简单解释一下。

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    [*1]:多线程上下文中的术语“争用”意味着许多线程试图同时访问/调用/更新某些东西;在这种情况下,LongAdder 或一般的计数器。

    [*2]:此上下文中的旧值是LongAdder 的先前值。 AtomicLong 的所有更新方法,除了 set 和一些 CAS 方法,返回之前存储的值,LongAdder#increment 返回 void。新值就是 .. 新值,您可以通过 sum 获得。

    LongAdder 类的工作方式与 AtomicLong 不同,以增加吞吐量,这就是为什么例如increment 不返回任何内容。你可以在这里阅读:How LongAdder performs better than AtomicLong

    【讨论】:

      【解决方案2】:

      LongAdder 不保持一个值。当您增加/添加一个新值时,它会在不同的单元格中存储 1 个或新值。它不保持总价值。

      当您想获得实际值时,您调用 sum() 方法,该方法对所有值求和以获得结果。

      为了更好地理解,下面是 LongAdder 中 sum 方法的实现方式:

       public long sum() {
              Cell[] cs = cells;
              long sum = base;
              if (cs != null) {
                  for (Cell c : cs)
                      if (c != null)
                          sum += c.value;
              }
              return sum;
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-06-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-01
        • 2015-08-21
        • 2017-12-29
        相关资源
        最近更新 更多