ConcurrentHashMap是線程安全的HashMap阎毅。
-
在jdk1.7中,ConCurrentHashMap采用分段鎖機制点弯,將數據分成一段一段的存儲,給每一段數據配一把鎖抢肛,當一個線程占用鎖訪問其中一個段數據的時候,其他段的數據也能被其他線程訪問捡絮。
1.1 ConCurrentHashMap由一個Segment數組和多個HashEntry組成。Segment和HashEntry都是靜態(tài)內部類福稳。
1.1 Segment繼承重入鎖ReentrantLock涎拉,一個Segment包含一個HashEntry數組的圆。
1.2 HashEntry用于封裝映射表的鍵-值對鼓拧,每個HashEntry是一個鏈表結構的元素略板。
1.3 當對HashEntry數組中的元素進行修改時毁枯,首先會獲取它對應的Segment鎖叮称。
1.4 put操作:key會進行兩次hash,第一次key的hash用于定位Segment位置瓤檐,如果該Segment還未被賦值,則通過CAS進行賦值挠蛉。第二次key的hash用于找到HashEntry位置,定位到HashEntry的鏈表頭部肄满。
1.5 get操作:也是會經過兩次hash质涛,第一次key的hash用于定位Segment位置,第二次key的hash用于找到HashEntry位置汇陆。,然后遍歷該HashEntry下的鏈表進行對比毡代,成功就返回,不成功就返回nul
jdk1.7 ConCurrentHashMap.png -
jdk1.8中教寂,采用Node+CAS+Synchronized來保證并發(fā)安全。取消了Segment類执庐,直接鎖定HashEntry,降低了鎖的粒度轨淌。
2.1 Node是ConcurrentHashMap存儲結構的基本單元,繼承于HashMap中的Entry猿诸,用于存儲數據婚被。
2.2 put操作:根據key計算出hashCode梳虽,根據hashCode定位Node址芯,判斷當前Node是否為null窜觉,為null則寫入數據谷炸,利用CAS自旋機制保證寫入數據成功禀挫。不為null,則利用Synchronized鎖寫入數據语婴。如果數量大于8則要轉換為紅黑樹描孟。
2.3 get操作:根據計算出來的 hashcode 尋址砰左,是紅黑樹那就按照樹的方式獲取值匿醒。如果不滿足那就按照鏈表的方式遍歷獲取值缠导。
jdk1.8 ConCurrentHashMap.png