Is ConcurrentHashMap totally safe?

The get() method is thread-safe, and the other users gave you useful answers regarding this particular issue.

However, although ConcurrentHashMap is a thread-safe drop-in replacement for HashMap, it is important to realize that if you are doing multiple operations you may have to change your code significantly. For example, take this code:

if (!map.containsKey(key)) 
   return map.put(key, value);
else
   return map.get(key);

In a multi-thread environment, this is a race condition. You have to use the ConcurrentHashMap.putIfAbsent(K key, V value) and pay attention to the return value, which tells you if the put operation was successful or not. Read the docs for more details.


Answering to a comment that asks for clarification on why this is a race condition.

Imagine there are two threads A, B that are going to put two different values in the map, v1 and v2 respectively, having the same key. The key is initially not present in the map. They interleave in this way:

  • Thread A calls containsKey and finds out that the key is not present, but is immediately suspended.
  • Thread B calls containsKey and finds out that the key is not present, and has the time to insert its value v2.
  • Thread A resumes and inserts v1, “peacefully” overwriting (since put is threadsafe) the value inserted by thread B.

Now thread B “thinks” it has successfully inserted its very own value v2, but the map contains v1. This is really a disaster because thread B may call v2.updateSomething() and will “think” that the consumers of the map (e.g. other threads) have access to that object and will see that maybe important update (“like: this visitor IP address is trying to perform a DOS, refuse all the requests from now on”). Instead, the object will be soon garbage collected and lost.

Leave a Comment