【问题标题】:Long primitive or AtomicLong for a counter?长原语或 AtomicLong 计数器?
【发布时间】:2010-03-15 14:57:52
【问题描述】:

我需要一个 long 类型的计数器,具有以下要求/事实:

  • 递增计数器应该花费尽可能少的时间。
  • 计数器只能由一个线程写入。
  • 从计数器读取将在另一个线程中完成。
  • 计数器会定期递增(每秒最多几千次),但每五秒只会读取一次。
  • 精确的准确性并不重要,只需粗略了解计数器的大小就足够了。
  • 计数器永远不会被清除,会递减。

根据这些要求,您会选择如何实施您的计数器?作为简单的long,作为volatile long 还是使用AtomicLong?为什么?

目前我有一个volatile long,但想知道另一种方法是否会更好。我还通过 ++counter 而不是 counter++ 来增加我的多头。因为没有完成任务,这真的更有效吗(正如我在其他地方被引导相信的那样)?

【问题讨论】:

  • volatile 应该没问题,因为合约规定对 volatile 变量的每次读取都发生在先前写入的锁定释放之后。
  • 如果您每秒只更新几千次并使用非嵌入式处理器,则差异无关紧要;如今,您可以在几乎任何机器上每秒进行数百万次AtomicLong 更新。不过,我同意volatile 应该足够了。如果您想确定的话,您可以同时对两者进行编码并检查它们匹配的频率(以及它们何时不匹配)。
  • @Riduidel 我们正在计算传入的数据包,我并不介意这个数字是 12,345,678 还是稍晚于 12,345,602

标签: java performance java.util.concurrent


【解决方案1】:

鉴于这些要求,我认为 volatile long 应该就足够了。非volatile long 的计数器不会不正确,但在这种情况下,阅读器可能会读取过时的信息。

一个问题是,如果没有声明volatile,则JVM specificationlong 的读写是not required to be atomic。这意味着如果读取线程在写入线程已更新值的一部分而不是另一部分时读取该值,则读取线程可能会获得几乎虚构的值。

++countercounter++ 之间的区别可能无关紧要,因为 JVM 会意识到不再使用表达式的值,并且在这种情况下两者是等价的。

【讨论】:

    【解决方案2】:

    在 Java 8 中,使用 LongAdder,它甚至比线程争用高的 AtomicLong 更好。

    LongAdder JavaDoc:

    当多个线程更新用于收集统计信息等目的的公共总和时,此类通常比 AtomicLong 更可取,而不是用于细粒度的同步控制。在低更新争用下,这两个类具有相似的特征。但在高争用情况下,该类的预期吞吐量明显更高,代价是更高的空间消耗。

    【讨论】:

    • 争用不高。只有一个线程会写入。
    【解决方案3】:

    您的程序的正常运行时间要求是多少?您可以使用非易失性 int 和 racy-reads 吗?

    【讨论】:

    • 正常运行时间尽可能长 - 这是在服务器内部运行。
    【解决方案4】:

    10^4 增量/秒是每 100 微秒 1。效率不是问题,但原子性可能是问题。您可能有 2 个副本,当读取时,如果它们不相等,请再次读取。

    【讨论】:

      【解决方案5】:

      article 讨论了实现计数器的可能方法 我认为这个实现应该适合你

      class LessNaiveVolatieIdGenerator {
      private static volatile long id = 0;
      public static long nextId() {
          long nextId = (id = id + 1); // or nextId = id++;
          return nextId;
      }
      

      }

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-03-15
        • 1970-01-01
        • 1970-01-01
        • 2017-03-05
        • 2015-04-22
        • 2011-04-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多