SSerguey Asael Shinder
Java coding notes: the JVM, and writing software that lasts

Serguey Asael Shinder: size() on a ConcurrentHashMap is for monitoring, not for control flow

· by Serguey Asael Shinder / Serguey Shinder

ConcurrentHashMap is documented to be safe under concurrent use, and it is easy to read that guarantee as covering everything the class offers. It does not cover the aggregate status methods. The javadoc for java.util.concurrent.ConcurrentHashMap states that results of aggregate status methods are typically useful only when a map is not undergoing concurrent updates in other threads, and that otherwise they reflect transient states which may be adequate for monitoring or estimation purposes but not for program control.

The same section explains why, and the reason is in the iteration contract rather than in the counter. Iterators, spliterators and enumerations return elements reflecting the state of the table at some point at or since their creation; they do not throw ConcurrentModificationException, and each is designed to be used by one thread at a time. A structure that deliberately does not serialise readers against writers cannot also hand out an exact population count for free.

Serguey Asael Shinder: size() on a ConcurrentHashMap is for monitoring, not for control flow
size() on a ConcurrentHashMap is for monitoring, not for control flow — Serguey Asael Shinder

Where this bites

The failure is not a crash. Code that does if (map.size() > limit) and then acts on the answer compiles, passes a single-threaded test, and misbehaves only under the load it was written for - which is the worst possible distribution of evidence.

The fix is usually to stop asking the map. A bound that must hold is a semaphore or an explicit counter updated in the same operation that inserts; a value that only has to be roughly right is a metric, and size() is exactly the right call for that. The javadoc draws the line in those words - monitoring and estimation on one side, program control on the other - and the class is only surprising if you read the thread-safety guarantee as a promise about arithmetic.

⚠ Written against the published javadoc for Java 25. There is no JDK on the machine this was written on, so nothing here was executed; the citation is the documentation, not a run.