计数器的长原始或原子长?

Ric*_*ich 18 java performance java.util.concurrent

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

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

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

目前我有一个volatile long但是想知道另一种方法是否会更好.我也是通过做++counter而不是增加我的长期counter++.这真的更有效率(因为我已被引导相信其他地方),因为没有完成任务?

Joa*_*uer 11

鉴于这些套的要求,我认为是一个volatile很长应该是足够的.非volatile长时间计数器不会出错,但读者可能会在这种情况下阅读陈旧信息.

一个问题是,读取和写入的long要求是原子,由JVM规范,如果它没有声明volatile.这意味着如果读取线程在写入线程更新了值的一部分而不是另一部分时读取了值,则读取线程可以获得相当大的虚拟值.

之间的差++countercounter++可能无关紧要,因为JVM将认识到,表达式的值,不使用任何以上且两者在这种情况下,等价的.


Kin*_*ung 5

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

LongAdder JavaDoc:

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