长原始还是原子长计数器?

2022-09-02 22:04:17

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

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

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

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


答案 1

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

一个问题是,如果不声明,根据JVM规范,读取和写入不需要是原子的。这意味着,如果读取线程在写入线程更新值的一部分而不是另一部分时读取该值,则读取线程可以获得几乎虚构的值。longvolatile

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


答案 2

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

LongAdder JavaDoc:

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


推荐