ConcurrencyMedium

Fix a counter that loses updates

The code below counts processed orders across a thread pool. In a single-threaded test it is always correct. In production it reports fewer orders than were processed, and the shortfall grows with load.

Fix it. Then answer the harder question: name the exact interleaving that loses an update.

Example

input8 threads × 100,000 incrementsoutput800000

The buggy version typically reports somewhere between 300,000 and 790,000, and never the same number twice.

Constraints

  • The fix must not serialise the whole pool — a synchronized block around the work defeats the point.
  • Do not change the number of threads.

Hints

Hint 1
count++ is a read, an add and a write. Nothing stops two threads reading the same value.
Hint 2
volatile makes the write visible. It does not make the three steps one step.
Hint 3
AtomicLong, or LongAdder if the contention is high enough to matter.

Stuck? The lesson behind this problem: 🧵 synchronized and volatile

java
Tab indents · Escape first to tab out

Test cases

These are the specification. Run tests checks your answer against them.

CaseInputExpected
8 threads, 100k increments eachthreads=8, each=100000800000
1 thread (must not regress)threads=1, each=100000100000
high contentionthreads=64, each=500003200000