compute, merge and computeIfAbsent hold a lock on the bin for that key, so concurrent updates cannot lose a write the way get-then-put can.
var hits = new ConcurrentHashMap<String, Integer>();
var pool = Executors.newFixedThreadPool(4);
for (int i = 0; i < 400; i++) {
pool.submit(() -> hits.merge("page", 1, Integer::sum));
}
pool.shutdown();
pool.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("expected 400, got " + hits.get("page"));
System.out.println("mappingCount = " + hits.mappingCount());
expected 400, got 400
mappingCount = 1
Run this yourself in the Online Java Compiler, spin up a live REST API in the API Sandbox, or practise with Java interview questions.
Published 2026-07-30