How does ConcurrentHashMap in Java achieve thread safety

  • 2021-12-09 08:51:48
  • OfStack

Directory syntax: ConcurrentHashmap Requirements: How to Make ConcurrentHashMap Thread Safe? Differences among Hashtable, Hashmap and ConcurrentHashmap

ConcurrentHashMap is a hash table that supports full concurrency for retrieval and high expected concurrency for updates. This class follows the same functional specification as Hashtable and contains all the methods of Hashtable. ConcurrentHashMap is in the java. util. Concurrent package.

Syntax:


public class ConcurrentHashMap<K,V>
extends AbstractMap<K,V>
implements ConcurrentMap<K,V>, Serializable

Where K refers to the type of key maintained by this mapping, and V refers to the type of mapping value

Requirements for ConcurrentHashmap:

Although HashMap has many advantages, it cannot be used for multithreading because it is not thread safe. Although Hashtable is considered to be thread-safe, it also has one drawback. For example, Hashtable needs to be locked to read open, even if it does not affect objects. n HashMap, if one thread is iterating over one object and another thread tries to access the same object, it throws ConcurrentModificationException, while concurrent hashmap does not throw ConcurrentModificationException.

How to make ConcurrentHashMap thread safe?

The java. util. Concurrent. ConcurrentHashMap class achieves thread safety by dividing map into segment. Instead of the entire object needing a lock, one segment, that is, one thread needs one segment lock. In ConcurrenHashap, the read operation does not require any locks.

Example 1:


import java.util.*;
import java.util.concurrent.*;

//  Expand Thread The main class of the class 
class GFG extends Thread {

 //  Create static  HashMap  Class object 
 static HashMap m = new HashMap();

 public void run()
 {

  // try  Block check exception 
  try {

   //  Let the thread sleep  3  Seconds 
   Thread.sleep(2000);
  }
  catch (InterruptedException e) {
  }
  System.out.println(" Sub-thread update mapping ");
  m.put(103, "C");
 }
 public static void main(String arg[])
  throws InterruptedException
 {
  m.put(101, "A");
  m.put(102, "B");
  GFG t = new GFG();
  t.start();
  Set s1 = m.keySet();
  Iterator itr = s1.iterator();
  while (itr.hasNext()) {
   Integer I1 = (Integer)itr.next();
   System.out.println(
    " The main thread iteration mapping and the current entry are :"
    + I1 + "..." + m.get(I1));
   Thread.sleep(3000);
  }
  System.out.println(m);
 }
}

Output:
The main thread iteration mapping and the current entry are: 101... A
Sub-thread update mapping
Exception in thread "main" java.util.ConcurrentModificationException
at java.base/java.util.HashMap$HashIterator.nextNode(HashMap.java:1493)
at java.base/java.util.HashMap$KeyIterator.next(HashMap.java:1516)
at Main.main(Main.java:30)

Output description:

The classes used in the above program extend the Thread class. Let's look at the control flow. Therefore, initially, the above java program contains 1 thread. When we encounter the statement Main t = new Main (), we are creating an object for the class that extends the Thread class. Therefore, whenever we call the t. start () method, the child thread is activated and calls the run () method. Now the main thread starts executing, throwing an exception called ConcurrentModificationException whenever the child thread updates the same map object.

Now let's use ConcurrentHashMap to modify the above program to resolve the exception generated when the above program is executed.

Example 2:


import java.util.*;
import java.util.concurrent.*;

class Main extends Thread {
 static ConcurrentHashMap<Integer, String> m
  = new ConcurrentHashMap<Integer, String>();
 public void run()
 {
  try {
   Thread.sleep(2000);
  }
  catch (InterruptedException e) {
  }
  System.out.println(" Sub-thread update mapping ");
  m.put(103, "C");
 }
 public static void main(String arg[])
  throws InterruptedException
 {
  m.put(101, "A");
  m.put(102, "B");
  Main t = new Main();
  t.start();
  Set<Integer> s1 = m.keySet();
  Iterator<Integer> itr = s1.iterator();
  while (itr.hasNext()) {
   Integer I1 = itr.next();
   System.out.println(
    " The main thread iteration mapping and the current entry are :"
    + I1 + "..." + m.get(I1));
   Thread.sleep(3000);
  }
  System.out.println(m);
 }
}

Output

The main thread iteration mapping and the current entry are: 101... A
Sub-thread update mapping
The main thread iteration mapping and the current entry are: 102... B
The main thread iteration mapping and the current entry are: 103... C
{101=A, 102=B, 103=C}

Output description:
The Class used in the above program extends the Thread class. Let's look at the control flow, so we know that in ConcurrentHashMap, while one thread is iterating, the remaining threads can perform any modifications in a safe way. In the above program, the main thread is updating the Map, while the child thread is also trying to update the Map object. This program does not throw ConcurrentModificationException.

Differences among Hashtable, Hashmap and ConcurrentHashmap

Hashtable Hashmap ConcurrentHashmap
我们将通过锁定整个地图对象来获得线程安全。 它不是线程安全的。 我们将获得线程安全,而无需使用段级锁锁定 Total Map 对象。
每个读写操作都需要1个objectstotal 映射对象锁。 它不需要锁。 读操作可以不加锁执行,写操作可以用段级锁执行。
1次只允许1个线程在地图上操作(同步) 不允许同时运行多个线程。它会抛出异常 1次允许多个线程以安全的方式操作地图对象
当1个线程迭代 Map 对象时,其他线程不允许修改映射,否则我们会得到 ConcurrentModificationException 当1个线程迭代 Map 对象时,其他线程不允许修改映射,否则我们会得到 ConcurrentModificationException 当1个线程迭代 Map 对象时,其他线程被允许修改地图,我们不会得到 ConcurrentModificationException
键和值都不允许为 Null HashMap 允许1个空键和多个空值 键和值都不允许为 Null。
在 1.0 版本中引入 在 1.2 版本中引入 在 1.5 版本中引入


Related articles: