Java ConcurrentHashMap鎖分段機(jī)制使用及代碼實(shí)例
概述
鎖分段機(jī)制ConcurrentHashMap
線程安全的hash表 每一段都是一個(gè)獨(dú)立的鎖
Java 5.0 在 java.util.concurrent
包中提供了多種并發(fā)容器類來(lái)改進(jìn)同步容器的性能。
ConcurrentHashMap 同步容器類是Java 5 增加的一個(gè)線程安全的哈希表。對(duì)與多線程的操作,介于 HashMap 與 Hashtable 之間。內(nèi)部采用“鎖分段”機(jī)制替代 Hashtable 的獨(dú)占鎖。進(jìn)而提高性能。
此包還提供了設(shè)計(jì)用于多線程上下文中的 Collection 實(shí)現(xiàn):ConcurrentHashMap、 ConcurrentSkipListMap、 ConcurrentSkipListSet、CopyOnWriteArrayList 和 CopyOnWriteArraySet。當(dāng)期望許多線程訪問(wèn)一個(gè)給定 collection 時(shí), ConcurrentHashMap 通常優(yōu)于同步的 HashMap,ConcurrentSkipListMap 通常優(yōu)于同步的 TreeMap。當(dāng)期望的讀數(shù)和遍歷遠(yuǎn)遠(yuǎn)大于列表的更新數(shù)時(shí), CopyOnWriteArrayList 優(yōu)于同步的 ArrayList。
ConcurrentHashMap就是一個(gè)線程安全的hash表。我們知道HashMap是線程不安全的,Hashtable加了鎖,是線程安全的,因此它效率低。
HashTable加鎖就是將整個(gè)hash表鎖起來(lái),當(dāng)有多個(gè)線程訪問(wèn)時(shí),同一時(shí)間只能有一個(gè)線程訪問(wèn),并行變成串行,因此效率低。所以JDK1.5后提供了ConcurrentHashMap,它采用了鎖分段機(jī)制。
1.8以后底層又換成了CAS,把鎖分段機(jī)制放棄了。CAS基本就達(dá)到了無(wú)鎖的境界。
詳解
ConcurrentHashMap
是 Java 中的一個(gè)線程安全的哈希表,它在多線程環(huán)境下提供了高效的讀取和更新操作。
從 Java 8 開(kāi)始,ConcurrentHashMap
引入了一種新的機(jī)制,稱為“鎖分段”(Segmentation with Locks),以提高并發(fā)性能。
鎖分段機(jī)制詳解
在 Java 8 之前的版本中,ConcurrentHashMap
使用分段鎖(Segmentation with Segments)來(lái)實(shí)現(xiàn)線程安全。每個(gè)段相當(dāng)于一個(gè)小型的哈希表,擁有自己的鎖。當(dāng)多個(gè)線程訪問(wèn)不同段的數(shù)據(jù)時(shí),它們可以并發(fā)進(jìn)行,從而減少了鎖的競(jìng)爭(zhēng)。
然而,Java 8 引入的鎖分段機(jī)制進(jìn)一步優(yōu)化了這一點(diǎn)。在新的實(shí)現(xiàn)中:
- CAS 操作:
ConcurrentHashMap
使用了更多的無(wú)鎖編程技術(shù),如原子操作(Compare-And-Swap, CAS),來(lái)減少鎖的使用。 - Node 繼承結(jié)構(gòu):內(nèi)部結(jié)構(gòu)由
Node
、TreeNode
、TreeBin
等類組成,這些類繼承自Node
,形成了一個(gè)復(fù)雜的繼承結(jié)構(gòu)。 - Synchronized 粒度:在某些操作上,如擴(kuò)容和部分更新操作上,仍然使用了
synchronized
塊來(lái)保證線程安全。 - 減少鎖的競(jìng)爭(zhēng):通過(guò)減少鎖的使用,
ConcurrentHashMap
允許更高的并發(fā)性,因?yàn)榫€程可以在沒(méi)有鎖的情況下進(jìn)行大部分操作。
示例
下面是一個(gè)簡(jiǎn)單的 ConcurrentHashMap
使用示例:
import java.util.concurrent.ConcurrentHashMap; public class ConcurrentHashMapExample { public static void main(String[] args) { // 創(chuàng)建一個(gè) ConcurrentHashMap 實(shí)例 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 } }
在這個(gè)示例中,我們創(chuàng)建了一個(gè) ConcurrentHashMap
實(shí)例,并插入了一些數(shù)據(jù)。然后,我們啟動(dòng)了多個(gè)線程來(lái)并發(fā)地更新數(shù)據(jù)。
由于 ConcurrentHashMap
是線程安全的,即使在多線程環(huán)境下,這些操作也不會(huì)導(dǎo)致數(shù)據(jù)不一致的問(wèn)題。
注意事項(xiàng)
ConcurrentHashMap
在高并發(fā)環(huán)境下比Hashtable
或Collections.synchronizedMap
有更好的性能。ConcurrentHashMap
適用于讀多寫少的場(chǎng)景。- 在使用
ConcurrentHashMap
時(shí),仍然需要注意避免長(zhǎng)時(shí)間持有迭代器,因?yàn)樵诘^(guò)程中可能會(huì)有結(jié)構(gòu)性修改(如擴(kuò)容)。
ConcurrentHashMap
是 Java 并發(fā)包 java.util.concurrent
中的一個(gè)重要組件,它通過(guò)鎖分段機(jī)制提供了高效的并發(fā)訪問(wèn)能力。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring MVC--攔截器實(shí)現(xiàn)和用戶登陸例子
本文主要介紹了Spring MVC--攔截器實(shí)現(xiàn)和用戶登陸例子,具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-03-03Java框架Struts2實(shí)現(xiàn)圖片上傳功能
這篇文章主要為大家詳細(xì)介紹了Java框架Struts2實(shí)現(xiàn)圖片上傳功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-08-08java 線程中start方法與run方法的區(qū)別詳細(xì)介紹
這篇文章主要介紹了java 線程中start方法與run方法的區(qū)別詳細(xì)介紹的相關(guān)資料,在java線程中調(diào)用start方法與run方法的區(qū)別在哪里? 這兩個(gè)問(wèn)題是兩個(gè)非常流行的初學(xué)者級(jí)別的多線程面試問(wèn)題,這里進(jìn)行詳細(xì)說(shuō)明,需要的朋友可以參考下2016-11-11通過(guò)Maven進(jìn)行jedis連接redis的實(shí)現(xiàn)
這篇文章主要介紹了通過(guò)Maven進(jìn)行jedis連接redis的實(shí)現(xiàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07深入理解Java中的HashMap的實(shí)現(xiàn)機(jī)制
這篇文章主要介紹了深入理解Java中的HashMap的實(shí)現(xiàn)機(jī)制,同時(shí)也有助于理解Java中對(duì)于哈希函數(shù)的相關(guān)處理方式,需要的朋友可以參考下2015-07-07