Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Long primitive or AtomicLong for a 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?

like image 736
Rich Avatar asked Mar 15 '10 14:03

Rich


People also ask

What is Atomic long?

An AtomicLong is used in applications such as atomically incremented sequence numbers, and cannot be used as a replacement for a Long . However, this class does extend Number to allow uniform access by tools and utilities that deal with numerically-based classes.

How AtomicLong works in java?

AtomicLong class provides operations on underlying long value that can be read and written atomically, and also contains advanced atomic operations. AtomicLong supports atomic operations on underlying long variable. It have get and set methods that work like reads and writes on volatile variables.

How do you increment an atomic long?

getAndIncrement() is an inbuilt method in java that increases the given value by one and returns the value before updation which is of data-type long. Parameters: The function does not accepts a single parameter. Return value: The function returns the value before increment operation is performed to the previous value.


2 Answers

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.

like image 172
Joachim Sauer Avatar answered Oct 19 '22 00:10

Joachim Sauer


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.

like image 38
Kin Cheung Avatar answered Oct 18 '22 23:10

Kin Cheung