用于计数器的 Long 原语还是 AtomicLong?
我需要一个 long
类型的计数器,并具有以下要求/事实:
- 增加计数器应该花费尽可能少的时间。
- 计数器只能由一个线程写入。
- 从计数器读取将在另一个线程中完成。
- 计数器将定期递增(每秒数千次),但每五秒仅读取一次。
- 精确度并不重要,只要大致了解计数器的大小就足够了。
- 计数器永远不会被清零、递减。
根据这些要求,您将选择如何实施您的计数器?作为简单的long
、作为易失性long
还是使用AtomicLong
?为什么?
目前我有一个易失性长
,但想知道另一种方法是否会更好。我还通过执行 ++counter
而不是 counter++
来增加我的多头。因为没有完成任务,这真的更有效吗(正如我在其他地方相信的那样)?
I have a need for a counter of type long
with the following requirements/facts:
- Incrementing the counter should take as little time as possible.
- The counter will only be written to by one thread.
- Reading from the counter will be done in another thread.
- The counter will be incremented regularly (as much as a few thousand times per second), but will only be read once every five seconds.
- Precise accuracy isn't essential, only a rough idea of the size of the counter is good enough.
- The counter is never cleared, decremented.
Based upon these requirements, how would you choose to implement your counter? As a simple long
, as a volatile long
or using an AtomicLong
? Why?
At the moment I have a volatile long
but was wondering whether another approach would be better. I am also incrementing my long by doing ++counter
as opposed to counter++
. Is this really any more efficient (as I have been led to believe elsewhere) because there is no assignment being done?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
考虑到这些要求,我认为
volatile
long 应该足够了。对于非易失性长整型,计数器不会出错,但在这种情况下,读者可能会读取过时的信息。一个问题是读取和写入
long
是 不要求是原子的,由JVM 规范(如果未声明易失性
)。这意味着如果读取线程在写入线程更新了该值的一部分而不是另一部分时读取该值,则它可以获得几乎虚构的值。++counter
和counter++
之间的差异可能是无关紧要的,因为 JVM 会意识到表达式的值不再被使用,并且在这种情况下两者是等效的。Given these sets of requirements, I think that a
volatile
long should be sufficient. The counter wouldn't be incorrect with a non-volatile
long, but the reader might be reading stale information in that case.One problem is that reads and writes to a
long
are not required to be atomic, by the JVM specification if it is not declaredvolatile
. That would mean that the reading thread could get a pretty much fictive value if it reads the value while the writing thread has updated one part of the value, but not the other one.The difference between
++counter
andcounter++
is probably irrelevant, as the JVM will realize that the value of the expression is not used any more and the two are equivalent in this case.在 Java 8 中,使用 LongAdder 甚至比线程争用较高的 AtomicLong 更好。
LongAdder JavaDoc:
In Java 8, use LongAdder which is even better than AtomicLong where thread contention is high.
LongAdder JavaDoc:
您的程序的正常运行时间要求是多少?您可以使用非易失性 int 和 racy-reads 来凑合吗?
what's the uptime requirement for your program? Could you make do with an un-volatile int and racy-reads?
10^4 增量/秒是每 100 usec 1。效率不是问题,但原子性可能是问题。你可能有 2 个副本,当读取它时,如果它们不相等,请再读取一次。
10^4 increments / second is 1 every 100 usec. Efficiency is not an issue, but atomicity might be. You might have 2 copies of it, and when it is read, if they are not equal, read again.
这篇文章讨论了实现计数器的可能方法
我认为这个实现应该适合你
}
This article talks about the possible ways to implement a counter
I think this implementation should work for you
}