LongAdder
as an alternative to AtomicLong
ExecutorService executor = Executors.newFixedThreadPool(2);
IntStream.range(0, 1000)
.forEach(i -> executor.submit(adder::increment));
stop(executor);
System.out.println(adder.sumThenReset()); // => 1000
LongAccumulator
is a more generalized version of LongAdder
LongBinaryOperator op = (x, y) -> 2 * x + y;
LongAccumulator accumulator = new LongAccumulator(op, 1L);
ExecutorService executor = Executors.newFixedThreadPool(2);
IntStream.range(0, 10)
.forEach(i -> executor.submit(() -> accumulator.accumulate(i)));
stop(executor);
System.out.println(accumulator.getThenReset()); // => 2539
I have some queries.
LongAdder
always preferred to AtomicLong?LongAccumulator
preferred to both LongAdder and AtomicLong?The difference between those classes, and when to use one over the other, is mentioned in the Javadoc. From LongAdder
:
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.
And from LongAccumulator
:
This class is usually preferable to
AtomicLong
when multiple threads update a common value 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.[...]
Class
LongAdder
provides analogs of the functionality of this class for the common special case of maintaining counts and sums. The callnew LongAdder()
is equivalent tonew LongAccumulator((x, y) -> x + y, 0L)
.
Thus, the use of one over the other depends on what your application intends to do. It is not always strictly prefered, only when high concurrency is expected and you need to maintain a common state.
@Tunaki answered the question skillfully, but there is still one issue that affects the choice.
Adding to a Cell requires a Cell per thread. The internal code uses getProbe() in Striped64 which returns:
return UNSAFE.getInt(Thread.currentThread(), PROBE);
Probe is a system field used in threadLocalRandomSeed.
My understanding is that probe is unique for each thread. If you have a high number of threads create/destroy then probe is created for each new thread.
Therefore, the number of Cells may become excessive. If someone has more detail on this I would like to hear from you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With