LongAdder
LongAdder
LongAdder and LongMaxUpdater are key enabling technology.
Doug Lea and company have built some counters to do exactly what we need as part of JSR166e/JDK8. Avaje Metrics makes use of LongAdder and LongMaxUpdater (backported from JDK8). Some might say that Avaje Metrics is an glorified wrapper for LongAdder and LongMaxUpdater.
Compared to AtomicLong what LongAdder does is massively reduce potential contention when multiple threads are updating the value. It does this by splitting the single counter into multiple counters.
The costs of this approach relative to AtomicLong are:
- More memory - Multiple underlying long values
- Slower reads - A read means that all the underlying values need to be sumed up
- Its not Atomic - The returned sum is NOT an atomic snapshot; invocation in the absence of concurrent updates returns an accurate result, but concurrent updates that occur while the sum is being calculated might not be incorporated.
For the Avaje metrics we only read periodically when we collect the metrics and this is done in a background thread. We undestand that relative to AtomicLong it takes a little more memory and is not atomic but this is more than offset by the fact that we can safely add it into our application code without the concern that it would increase contention.
JavaDoc for LongAdder
/**
* One or more variables that together maintain an initially zero
* {@code long} sum. When updates (method {@link #add}) are contended
* across threads, the set of variables may grow dynamically to reduce
* contention. Method {@link #sum} (or, equivalently, {@link
* #longValue}) returns the current total combined across the
* variables maintaining the sum.
*
* This class is usually preferable to {@link 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.
*
* This class extends {@link Number}, but does <em>not</em> define
* methods such as {@code equals}, {@code hashCode} and {@code
* compareTo} because instances are expected to be mutated, and so are
* not useful as collection keys.
*
* <em>jsr166e note: This class is targeted to be placed in
* java.util.concurrent.atomic.</em>
*
* @since 1.8
* @author Doug Lea
*/
public class LongAdder extends Striped64 implements Serializable {