用于计数器的 Long 原语还是 AtomicLong?

发布于 2024-08-25 08:47:30 字数 485 浏览 5 评论 0原文

我需要一个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

冰葑 2024-09-01 08:47:30

考虑到这些要求,我认为 volatile long 应该足够了。对于非易失性长整型,计数器不会出错,但在这种情况下,读者可能会读取过时的信息。

一个问题是读取和写入 long要求是原子的,由JVM 规范(如果未声明易失性)。这意味着如果读取线程在写入线程更新了该值的一部分而不是另一部分时读取该值,则它可以获得几乎虚构的值。

++countercounter++ 之间的差异可能是无关紧要的,因为 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 declared volatile. 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 and counter++ 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.

鱼忆七猫命九 2024-09-01 08:47:30

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

LongAdder JavaDoc:

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

In Java 8, use LongAdder which is even better than AtomicLong where thread contention is high.

LongAdder JavaDoc:

This class is usually preferable to AtomicLong when multiple threads update a common sum that is used for purposes such as collecting statistics, not for fine-grained synchronization control. Under low update contention, the two classes have similar characteristics. But under high contention, expected throughput of this class is significantly higher, at the expense of higher space consumption.

や莫失莫忘 2024-09-01 08:47:30

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

what's the uptime requirement for your program? Could you make do with an un-volatile int and racy-reads?

无所谓啦 2024-09-01 08:47:30

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.

落叶缤纷 2024-09-01 08:47:30

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

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

}

This article talks about the possible ways to implement a counter
I think this implementation should work for you

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

}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文