Informally, you can think of a Map as an set of "variables", each "variable" is addressed by a key (instead of a static name of an ordinary variable).
(An array is formally a list of variables, each addressed by an integer index.)
In HashMap, these "variables" are like "plain" variables; if you access a "variable" concurrently, things may go wrong (just like ordinary non-volatile variables)
In ConcurrentHashMap, these "variables" have volatile
semantics. Therefore it is "more" safe to use concurrently. For example, a write will be visible to the "subsequent" read.
Of course, volatile
is not enough sometimes; for example, we know we cannot use a volatile int for atomic increments (without locking). We need new devices, like AtomicInteger, for atomic operations.
Fortunately, in Java 8, new atomic methods are added to ConcurrentHashMap, so that now we can operate on these "variables" atomically. See if the compute()
method may fit your use case.