Java Concurrency Interview

Concurrent collections question 77 of 180 junior

Many threads count words into one map. How do you make the counting correct?

Every call on a ConcurrentHashMap is thread safe, but two calls in a row are not one operation. With get then put, two threads read the same count, both add one, and one increment is lost. The map is fine; the read-modify-write around it is the race. A synchronized wrapper has exactly the same hole, because it locks each call, not the pair.

The fix is to hand the whole update to the map, which runs it atomically for that key:

ConcurrentHashMap<String, Long> counts = new ConcurrentHashMap<>();
counts.merge(word, 1L, Long::sum);

compute and computeIfAbsent give the same per-key guarantee. When one key is very hot, the threads queue on that key's bin, and the usual next step is a LongAdder per key: counts.computeIfAbsent(word, k -> new LongAdder()).increment(). The map lookup is then read-only for existing words, and the increment spreads over cells.

concurrenthashmap merge atomicity

Quiz yourself on Concurrent collections Suggest a correction