I have a CHM defined as below. I am calling setDataProcess
method from a single background thread whenever there is any update. And I am calling getDataMapping
from multiple reader threads always.
private static final ConcurrentHashMap<ProcessType, Mapping> mappingsHolder = new ConcurrentHashMap<ProcessType, Mapping>();
private static final CountDownLatch hasInitialized = new CountDownLatch(ProcessType.values().length);
public static void setDataProcess(ProcessType processType, Mapping newMapData) {
mappingsHolder.put(processType, newMapData);
hasInitialized.countDown();
}
public static Mapping getDataMapping(ProcessType processType) {
try {
hasInitialized.await();
return mappingsHolder.get(processType);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IllegalStateException(e);
}
}
Question is - Any change in mappingsHolder
CHM will be visible to all the reader threads instantly or I need to use volatile for that?
As far as I can see, you're using a CountDownLatch
in the read method to wait until the count reaches zero. The count is apparently the number of enum constants in ProcessType
. If this CountDownLatch
is properly implemented, there shouldn't be a problem since according to the javadocs, there should be a happens-before relationship:
Memory consistency effects: Until the count reaches zero, actions in a thread prior to calling
countDown()
happen-before actions following a successful return from a correspondingawait()
in another thread.
Ignoring the CountDownLatch
factor, the ConcurrentHashMap
does not synchronize on a retrieval of a key but retrieves the most recent value corresponding to a key.
Retrieval operations (including
get
) generally do not block, so may overlap with update operations (includingput
andremove
). Retrievals reflect the results of the most recently completed update operations holding upon their onset.
This means changes done by a thread are visible to a thread reading a key. But the two can interfere.