Java ConcurrentHashMap鎖分段機制使用及代碼實例
概述
鎖分段機制ConcurrentHashMap
線程安全的hash表 每一段都是一個獨立的鎖
Java 5.0 在 java.util.concurrent 包中提供了多種并發(fā)容器類來改進同步容器的性能。
ConcurrentHashMap 同步容器類是Java 5 增加的一個線程安全的哈希表。對與多線程的操作,介于 HashMap 與 Hashtable 之間。內(nèi)部采用“鎖分段”機制替代 Hashtable 的獨占鎖。進而提高性能。
此包還提供了設(shè)計用于多線程上下文中的 Collection 實現(xiàn):ConcurrentHashMap、 ConcurrentSkipListMap、 ConcurrentSkipListSet、CopyOnWriteArrayList 和 CopyOnWriteArraySet。當期望許多線程訪問一個給定 collection 時, ConcurrentHashMap 通常優(yōu)于同步的 HashMap,ConcurrentSkipListMap 通常優(yōu)于同步的 TreeMap。當期望的讀數(shù)和遍歷遠遠大于列表的更新數(shù)時, CopyOnWriteArrayList 優(yōu)于同步的 ArrayList。
ConcurrentHashMap就是一個線程安全的hash表。我們知道HashMap是線程不安全的,Hashtable加了鎖,是線程安全的,因此它效率低。
HashTable加鎖就是將整個hash表鎖起來,當有多個線程訪問時,同一時間只能有一個線程訪問,并行變成串行,因此效率低。所以JDK1.5后提供了ConcurrentHashMap,它采用了鎖分段機制。

1.8以后底層又換成了CAS,把鎖分段機制放棄了。CAS基本就達到了無鎖的境界。
詳解
ConcurrentHashMap 是 Java 中的一個線程安全的哈希表,它在多線程環(huán)境下提供了高效的讀取和更新操作。
從 Java 8 開始,ConcurrentHashMap 引入了一種新的機制,稱為“鎖分段”(Segmentation with Locks),以提高并發(fā)性能。
鎖分段機制詳解
在 Java 8 之前的版本中,ConcurrentHashMap 使用分段鎖(Segmentation with Segments)來實現(xiàn)線程安全。每個段相當于一個小型的哈希表,擁有自己的鎖。當多個線程訪問不同段的數(shù)據(jù)時,它們可以并發(fā)進行,從而減少了鎖的競爭。
然而,Java 8 引入的鎖分段機制進一步優(yōu)化了這一點。在新的實現(xiàn)中:
- CAS 操作:
ConcurrentHashMap使用了更多的無鎖編程技術(shù),如原子操作(Compare-And-Swap, CAS),來減少鎖的使用。 - Node 繼承結(jié)構(gòu):內(nèi)部結(jié)構(gòu)由
Node、TreeNode、TreeBin等類組成,這些類繼承自Node,形成了一個復(fù)雜的繼承結(jié)構(gòu)。 - Synchronized 粒度:在某些操作上,如擴容和部分更新操作上,仍然使用了
synchronized塊來保證線程安全。 - 減少鎖的競爭:通過減少鎖的使用,
ConcurrentHashMap允許更高的并發(fā)性,因為線程可以在沒有鎖的情況下進行大部分操作。
示例
下面是一個簡單的 ConcurrentHashMap 使用示例:
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentHashMapExample {
public static void main(String[] args) {
// 創(chuàng)建一個 ConcurrentHashMap 實例
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
// 插入數(shù)據(jù)
map.put("One", 1);
map.put("Two", 2);
map.put("Three", 3);
// 讀取數(shù)據(jù)
System.out.println(map.get("Two")); // 輸出 2
// 并發(fā)更新數(shù)據(jù)
for (int i = 0; i < 10; i++) {
int finalI = i;
new Thread(() -> map.put("Key" + finalI, finalI)).start();
}
// 等待所有線程完成
while (Thread.activeCount() > 1) {
Thread.yield();
}
// 輸出更新后的數(shù)據(jù)
System.out.println(map.get("Key9")); // 輸出 9
}
}在這個示例中,我們創(chuàng)建了一個 ConcurrentHashMap 實例,并插入了一些數(shù)據(jù)。然后,我們啟動了多個線程來并發(fā)地更新數(shù)據(jù)。
由于 ConcurrentHashMap 是線程安全的,即使在多線程環(huán)境下,這些操作也不會導(dǎo)致數(shù)據(jù)不一致的問題。
注意事項
ConcurrentHashMap在高并發(fā)環(huán)境下比Hashtable或Collections.synchronizedMap有更好的性能。ConcurrentHashMap適用于讀多寫少的場景。- 在使用
ConcurrentHashMap時,仍然需要注意避免長時間持有迭代器,因為在迭代過程中可能會有結(jié)構(gòu)性修改(如擴容)。
ConcurrentHashMap 是 Java 并發(fā)包 java.util.concurrent 中的一個重要組件,它通過鎖分段機制提供了高效的并發(fā)訪問能力。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
EDI中JAVA通過FTP工具實現(xiàn)文件上傳下載實例
這篇文章主要介紹了EDI中JAVA通過FTP工具實現(xiàn)文件上傳下載實例,具有一定的參考價值,有需要的可以了解一下。2016-11-11
Java Socket使用加密協(xié)議進行傳輸對象的方法
這篇文章主要介紹了Java Socket使用加密協(xié)議進行傳輸對象的方法,結(jié)合實例形式分析了java socket加密協(xié)議相關(guān)接口與類的調(diào)用方法,以及服務(wù)器、客戶端實現(xiàn)技巧,需要的朋友可以參考下2017-06-06
ibatis結(jié)合oracle批量插入三種方法的測評
今天小編就為大家分享一篇關(guān)于ibatis結(jié)合oracle批量插入三種方法的測評,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-12-12
SpringBoot Redisson 集成的實現(xiàn)示例
本文主要介紹了SpringBoot Redisson 集成的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-05-05
Java數(shù)據(jù)結(jié)構(gòu)與算法實現(xiàn)遞歸與回溯
本文主要介紹了Java數(shù)據(jù)結(jié)構(gòu)與算法實現(xiàn)遞歸與回溯,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03

