ConcurrentHashMap

HashTable性能差主要是由于所有操作需要競爭同一把鎖,而如果容器中有多把鎖,每一把鎖鎖一段數(shù)據(jù),這樣在多線程訪問時不同段的數(shù)據(jù)時,就不會存在鎖競爭了,這樣便可以有效地提高并發(fā)效率。這就是ConcurrentHashMap所采用的"分段鎖"思想。

put的主要邏輯也就兩步:1.定位segment并確保定位的Segment已初始化 2.調(diào)用Segment的put方法。

get方法無需加鎖,由于其中涉及到的共享變量都使用volatile修飾,volatile可以保證內(nèi)存可見性,所以不會讀取到過期數(shù)據(jù)。

ConcurrentHashMap作為一種線程安全且高效的哈希表的解決方案,尤其其中的"分段鎖"的方案,相比HashTable的全表鎖在性能上的提升非常之大。

1 ConcurrentHashMap 和 Hashtable 的區(qū)別
ConcurrentHashMap 和 Hashtable 的區(qū)別主要體現(xiàn)在實(shí)現(xiàn)線程安全的?式上不同。
底層數(shù)據(jù)結(jié)構(gòu): JDK1.7的 ConcurrentHashMap 底層采? 分段的數(shù)組+鏈表 實(shí)現(xiàn),JDK1.8 采?
的數(shù)據(jù)結(jié)構(gòu)跟HashMap1.8的結(jié)構(gòu)?樣,數(shù)組+鏈表/紅??叉樹。Hashtable 和 JDK1.8 之前的
HashMap 的底層數(shù)據(jù)結(jié)構(gòu)類似都是采? 數(shù)組+鏈表 的形式,數(shù)組是 HashMap 的主體,鏈表則是
主要為了解決哈希沖突?存在的;
實(shí)現(xiàn)線程安全的?式(重要): ① 在JDK1.7的時候,ConcurrentHashMap(分段鎖) 對整個桶
數(shù)組進(jìn)?了分割分段(Segment),每?把鎖只鎖容器其中?部分?jǐn)?shù)據(jù),多線程訪問容器?不同數(shù)
據(jù)段的數(shù)據(jù),就不會存在鎖競爭,提?并發(fā)訪問率。 到了 JDK1.8 的時候已經(jīng)摒棄了Segment的
概念,?是直接? Node 數(shù)組+鏈表+紅?樹的數(shù)據(jù)結(jié)構(gòu)來實(shí)現(xiàn),并發(fā)控制使? synchronized 和
CAS 來操作。(JDK1.6以后 對 synchronized鎖做了很多優(yōu)化) 整個看起來就像是優(yōu)化過且線
程安全的 HashMap,雖然在JDK1.8中還能看到 Segment 的數(shù)據(jù)結(jié)構(gòu),但是已經(jīng)簡化了屬性,只
是為了兼容舊版本;② Hashtable(同?把鎖) :使? synchronized 來保證線程安全,效率?常
低下。當(dāng)?個線程訪問同步?法時,其他線程也訪問同步?法,可能會進(jìn)?阻塞或輪詢狀態(tài),如
使? put 添加元素,另?個線程不能使? put 添加元素,也不能使? get,競爭會越來越激烈
效率越低

?先將數(shù)據(jù)分為?段?段的存儲,然后給每?段數(shù)據(jù)配?把鎖,當(dāng)?個線程占?鎖訪問其中?個段數(shù)據(jù)時,其他段的數(shù)據(jù)也能被其他線程訪問

ConcurrentHashMap 是由 Segment 數(shù)組結(jié)構(gòu)和 HashEntry 數(shù)組結(jié)構(gòu)組成。

?個 ConcurrentHashMap ?包含?個 Segment 數(shù)組。Segment 的結(jié)構(gòu)和HashMap類似,是?種數(shù)組和鏈表結(jié)構(gòu),?個 Segment 包含?個 HashEntry 數(shù)組,每個 HashEntry 是?個鏈表結(jié)構(gòu)的元素,每個Segment 守護(hù)著?個HashEntry數(shù)組?的元素,當(dāng)對 HashEntry 數(shù)組的數(shù)據(jù)進(jìn)?修改時,必須?先獲得對應(yīng)的 Segment的鎖。

ConcurrentHashMap取消了Segment分段鎖,采?CAS和synchronized來保證并發(fā)安全。數(shù)據(jù)結(jié)構(gòu)跟
HashMap1.8的結(jié)構(gòu)類似,數(shù)組+鏈表/紅??叉樹。Java 8在鏈表?度超過?定閾值(8)時將鏈表(尋址時間復(fù)雜度為O(N))轉(zhuǎn)換為紅?樹(尋址時間復(fù)雜度為O(log(N)))
synchronized只鎖定當(dāng)前鏈表或紅??叉樹的?節(jié)點(diǎn),這樣只要hash不沖突,就不會產(chǎn)?并發(fā),效率?提升N倍

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容