When there are multiple threads modify and read a map at the same time, it can mess up the data and result in retrieving wrong information. There are several ways to solve this problem.
A. Atomic Access
This approach takes advantage of that reassigning a reference variable is atomic.
public class AtomicMapAccess {
private HashMap<String, Integer> theMap = new HashMap<>();
public void readMap() {
//The localReadMap will not be affected if a new map is assigned to theMap
//This step is atomic
HashMap<String, Integer> localReadMap = theMap;
Set<String> keys = localReadMap.keySet();
for (String key : keys) {
System.println(localReadMap.get(key));
}
}
public void modifyMap() {
//Create a new instance of map to take all the new set of data
HashMap<String, String> localModifyMap = new HashMap<>();
Random rand = new Random();
localModifyMap.put("key1", rand.nextInt());
localModifyMap.put("key2", rand.nextInt());
localModifyMap.put("key3", rand.nextInt());
//An atomic step to assign the map with new data to theMap.
theMap = localModifyMap;
}
public class writer implements Runnable {
public void run() {
modifyMap();
try {
Thread.sleep(20);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
public class reader implements Runnable {
public void run() {
readMap();
try {
Thread.sleep(20);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Thead[] writers = new Thread[3];
for (int i=0; i<writers.length; i++) {
writers[i] = new Thread(newWriter());
writers[i].start();
writers[i].join();
}
Thread[10] readers = new Thread[10];
for (int j=0; i<readers.length; j++) {
readers[j] = new Thread(new Reader());
readers[j].start();
readers[j].join();
}
}
}
This approach works fine if the size of the map is not very huge, for each time a thread modifies the map, it needs to reassign data from all the slots to the newly created map, which could be time consuming if the map is huge.
B. ConcurrentHashMap
ConcurrentHashMap<String, Integer> theMap = new ConcurrentHashMap<>();
With the ConcurrentHashMap, update is done with a lock at the hashmap basket level, so that is uses multiple locks. However, iterators are designed to be used by one Thread at a time.
C. Synchronized HashMap
Map<String, Integer> theMap = Collections.synchronizedMap(new HashMap<<>());
This approach guarantees serial access, It locks at the map level, which is less efficient. Furthermore, when navigating through the map with Iterators, it is imperative to do it in a synchronized block on the map.
Set<String> keys = theMap.keySet();
synchronized(theMap) {
for(String key : keys) {
Integer value = theMap.get(key);
}
}
-----------------------------------------------------------------------------------------------------------------
Watch the blessing and loving online channel:
SupremeMasterTV live
If you have ever asked yourself these questions, this is the book for you. What is the meaning of life? Why do people suffer? What is in control of my life? Why is life the way it is? How can I stop suffering and be happy? How can I have a successful life? How can I have a life I like to have? How can I be the person I like to be? How can I be wiser and smarter? How can I have good and harmonious relations with others? Why do people meditate to achieve enlightenment? What is the true meaning of spiritual practice? Why all beings are one? Read the book for free here.