Search code examples
javamultithreadingthread-safetyvolatileconcurrenthashmap

ConcurrentHashMap changes visible to all the threads?


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?


Solution

  • 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 corresponding await() 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 (including put and remove). 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.