How does ConcurrentHashMap in Java achieve thread safety
- 2021-12-09 08:51:48
- OfStack
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 版本中引入 |