Are size(), put(), remove(), get() atomic in Java synchronized HashMap?

10,481

Solution 1

A synchronized map as the name suggests is synchronized. Every operation on it is atomic in respect to any other operation on it.

You can think of it as if every method of your synchronized map is declared with a synchronized keyword.

Please bear in mind that although individual operations are atomic, if you combine them they're no longer atomic, for instance:

String value = map.get("key");
map.put("key", value+"2");

is not equivalent to your custom synchronized code:

synchronized (map) {
    String value = map.get("key");
    map.put("key", value+"2");
}

but rather:

synchronized (map) {
    String value = map.get("key");
}
synchronized (map) {
    map.put("key", value+"2");
}

Solution 2

A HashMap is not guaranteed to have atomic operations. Calling any of its methods from different threads (even size()) may corrupt the map. However, a map obtained using Collections.synchronizedMap will have each call synchronized (and hence thread-safe).

However, you may need higher-level synchronization. For instance, if you test whether a key is present, read the size, or otherwise access something from the map and then do something else with the map based on the result, the map may have changed between the two calls. In that case, you need a synchronized block to make the entire transaction atomic, rather than a synchronized map (that just makes each call atomic).

Solution 3

The map itself is synchronized, not some internal locks. Running more than one operation on the map does require a synchronized block. In any event, if you are using a JDK 1.6 or greater, you should consider using ConcurrentHashMap

ConcurrentHashMap is optimal when you need to ensure data consistency, and each of your threads need a current view of the map. If performance is critical, and each thread only inserts data to the map, with reads happening less frequently, then use the path you've outlined. That said, performance may only be poorer when only a single thread accesses a ConcurrentHashMap at a time, but significantly better when multiple threads access the map concurrently.

Share:
10,481
La-comadreja
Author by

La-comadreja

La-comadreja is the super cute and determined animal that inspires me when I attack a challenge head-on. I frequently contribute to Java, Ruby, algorithm and other questions on Stack Overflow and am active on Github under the same Username. I appreciate interesting and colorful applications of Computer Science that incorporate all different backgrounds. MS Computer Science, Columbia University. #SOreadytohelp

Updated on June 04, 2022

Comments

  • La-comadreja
    La-comadreja about 2 years

    I am declaring a Java Map as

    Map<String, String> map = Collections.synchronizedMap(new HashMap<String, String>());
    

    to deal with the concurrency issues, and synchronizing on the map for all the operations on it. However, I read that synchronization isn't necessary on a synchronizedMap when the operations are atomic. I checked the Java API and the documentation of HashMap doesn't seem to mention which are atomic, so I'm not sure which are.

    I'm synchronizing on the following calls to the map:

    map.size()
    
    map.put()
    
    map.remove()
    
    map.get()
    

    But if some are atomic, it seems synchronization isn't necessary for these. Which are atomic?