5

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?

john
  • 11,311
  • 40
  • 131
  • 251

3 Answers3

4

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.

M A
  • 71,713
  • 13
  • 134
  • 174
  • CDL is for one time synchronization during the startup but after that it has to be atomic update so CHM changes will be visible to all the threads? – john Jul 03 '15 at 18:08
  • Thanks for an edit so that means it will be an atomic update and any changes to CHM will be visible to all the threads right? – john Jul 03 '15 at 18:35
2

The CountdownLatch makes sure that actions prior to countDown happen-before another thread's return from await, as Manouti said.

As for the ConcurrentHashMap, the api documentation reads:

an update operation for a given key bears a happens-before relation with any (non-null) retrieval for that key reporting the updated value.

which should handle visibility of changes to the map to the threads reading from it.

Community
  • 1
  • 1
Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
0

Since the value of the variable (i.e. the location in memory of the map) will not change, then I doubt that volatile will make a difference here. The map-object, once allocated, won't be moving around.

But there is, as always, a potential timing issue: the threads could read a value before or after you have changed it. Basically, a concurrentHashMap won't be destroyed by being used by more than one thread at a time. As such, it's a necessary feature. But, that alone doesn't really address any other synchronization or notification requirements that the threads may require in order to successfully work together.

Mike Robinson
  • 8,490
  • 5
  • 28
  • 41