Thread-Safe Counter: synchronized, AtomicInteger and LongAdder
javaJavainterview-prepintermediatejava
Four threads increment three kinds of counters 50,000 times each, and every one of them ends at exactly 200,000.
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
public class ThreadSafeCounter {
public static void main(String[] args) {
SynchronizedCounter synced = new SynchronizedCounter();
AtomicInteger atomic = new AtomicInteger();
LongAdder adder = new LongAdder();
try (ExecutorService pool = Executors.newFixedThreadPool(4)) {
for (int t = 0; t < 4; t++) {
pool.submit(() -> {
for (int i = 0; i < 50_000; i++) {
synced.increment();
atomic.incrementAndGet();
adder.increment();
}
});
}
} // close() waits until all four tasks have finished
System.out.println(synced.value()); // 200000
System.out.println(atomic.get()); // 200000
System.out.println(adder.sum()); // 200000
}
}
// A lock around every access. Simple and correct, but threads queue up behind each other.
class SynchronizedCounter {
private int count;
synchronized void increment() { count++; }
synchronized int value() { return count; }
}
// AtomicInteger uses a compare-and-swap loop: no lock, good for moderate contention.
// LongAdder spreads updates over several cells and adds them up on read: best under heavy contention.