Friday, August 26, 2022

How to Synchronize HashMap in Java? Collections.synchronizedMap() Example Tutorial

Hello guys, if you have used HashMap class in Java before than you will know that HashMap is not synchronized, which means you cannot use it on multi-threaded Java programs without external synchronization. In other words, if you share an instance of HashMap between multiple threads, where each of them is either adding, removing or updating entries then it's possible that HashMap may lose its structure and not behave as expected. In simple words, exposing HashMap to multiple threads can corrupt the Map and you may not able to retrieve the data you want. If you have read my earlier article about HashMap, you know that during re-sizing its possible that HashMap exposed to multiple threads, may end up in an infinite loop. 

In order to avoid this, usually, one HashMap instance is used by one thread, sharing of HashMap instance is not allowed, but if you have to share HashMap and there is no option to avoid that, you can always synchronize HashMap in Java. 

Of course, this will affect the performance and probably reduce the speed of HashMap as synchronized method is always slower than the non-synchronized one. In this tutorial, we will learn how we can synchronize HashMap in Java.




Synchronizing HashMap in Java with Example

In this example, we have a HashMap<Integer, String> it is having integer keys and String type values. In order to synchronize it we are using Collections.synchronizedMap(hashmap)  it returns a thread-safe map backed up by the specified HashMap. In order to guarantee serial access, it is critical that all access to the backing map is accomplished through the returned map.


It is also mandatory that the user manually synchronizes on the returned map when iterating over any of its collection views:

   Map<Integer, String> synchronizedHashMaps = Collections.synchronizedMap(new HashMap<>());
      ...
  Set<Integer>  mySet = m.keySet();  // Needn't be in synchronized block
      ...
  synchronized(synchronizedHashMaps ) {  
      // Synchronizing on map instance, not set
      Iterator<Integer> i = mySet.iterator(); // Must be in synchronized block
      while (i.hasNext())
          foo(i.next());
  }
Failure to follow this advice may result in non-deterministic behavior. Also, the returned map will be serializable if the specified map is serializable. 

How to synchronize HashMap in Java




Collections.synchronizedMap() Example in Java

Here is a complete code example of how to synchronized HashMap in Java. You can run it in your favorite Java IDE or from the command prompt as you wish, just make sure you store this class in HashMapSynchronizationDemo.java file.


import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * This Java program demonstrate, how to synchronize HashMap in Java. 
 * 
 * @author WINDOWS 8
 */

public class HashMapSynchronizationDemo{

    public static void main(String args[]) {
        
        // HashMap with mapping containing country and their currency
        Map<String, String> currencies = new HashMap<String, String>();
        
        currencies.put("USA", "USD");
        currencies.put("England", "GBP");
        currencies.put("Canada", "CAD");
        currencies.put("HongKong", "HKD");
        currencies.put("Australia", "AUD");
        
        // Synchronizing HashMap in Java
        currencies = Collections.synchronizedMap(currencies);
        
        // Make sure to synchronize Map while Iterating 
        // getting key set can be outside synchronized block
        Set<String> keySet = currencies.keySet();  
        
        
        // Synchronizing on HashMap, not on Set
        synchronized(currencies) {  
            Iterator<String> itr = keySet.iterator(); 
           // Must be in synchronized block            
            while (itr.hasNext()){
                System.out.println(itr.next());
            }
        }
       
    }

}

Output
USA
Canada
HongKong
England
Australia

That's all about how do you synchronize HashMap in Java. Collections.synchronizedMap() is a useful method to achieve this but you also have better options available in Java. For example, if you know from the start that your HashMap will be shared between multiple threads then why not use ConcurrentHashMap, which is specially designed for such use. 

If you like this article and love to explore more in the world of HashMap, check out the following;
  • What is the difference between Hashtable and ConcurrentHashMap in Java? (difference)
  • How get method of HashMap works in Java? (answer)
  • How to traverse HashMap in Java? (example)
  • 21 Java HashMap Interview Questions with Answers (HashMap questions)
  • How to sort HashMap based upon keys and values in Java? (solution)
  • What is the difference between Hashtable and HashMap in Java? (answer)
  • 10 ConcurrentHashMap Interview Questions (concurrentMap questions)
  • Difference between HashSet and HashMap in Java? (answer)
  • 25 Examples of ConcurrentHashMAp in Java (concurrentMap example)
  • What is the difference between ArrayList and HashMap? (difference)
  • How HashSet internally works in Java? (answer)
  • How to convert Map to List in Java? (solution)
  • Difference between HashMap and LinkedHashMap in Java? (answer)
P. S. - If you are working on legacy Java version like before Java 1.5 then there is Hashtable class which provides similar functionality to synchronized HashMap. More often than not you will be using ConcurrentHashMap rather than Synchronized HashMap in Java. 

3 comments:

Feel free to comment, ask questions if you have any doubt.