ConcurrentHahMap 基於原始碼解析

2021-10-09 16:17:28 字數 1858 閱讀 4743

目錄

1、簡單總結

2、jdk1.7 segments + hashentry陣列 + 鍊錶解析

3、jdk1.8 雜湊表 + 紅黑樹 + cas 解析

參考:如下圖所示,segments繼承了可重入鎖reentrantlock,每個片段有乙個鎖,叫做「分段鎖」。

1).segment(分段鎖)

concurrenthashmap中的分段鎖稱為segment,它即類似於hashmap的結構,即內部擁有乙個entry陣列,陣列中的每個元素又是乙個鍊錶,同時又是乙個reentrantlock(segment繼承了reentrantlock)。

2).內部結構

concurrenthashmap使用分段鎖技術,將資料分成一段一段的儲存,然後給每一段資料配一把鎖,當乙個執行緒占用鎖訪問其中乙個段資料的時候,其他段的資料也能被其他執行緒訪問,能夠實現真正的併發訪問。如下圖是concurrenthashmap的內部結構圖:

從上面的結構我們可以了解到,concurrenthashmap定位乙個元素的過程需要進行兩次hash操作。

第一次hash定位到segment,第二次hash定位到元素所在的鍊錶的頭部。

3).該結構的優劣勢

壞處

這一種結構的帶來的***是hash的過程要比普通的hashmap要長

好處

寫操作的時候可以只對元素所在的segment進行加鎖即可,不會影響到其他的segment,這樣,在最理想的情況下,concurrenthashmap可以最高同時支援segment數量大小的寫操作(剛好這些寫操作都非常平均地分布在所有的segment上)。

所以,通過這一種結構,concurrenthashmap的併發能力可以大大的提高。

參考:

jdk8中concurrenthashmap參考了jdk8 hashmap的實現,採用了陣列+鍊錶+紅黑樹的實現方式來設計,內部大量採用cas操作。

cas:是compare and swap的縮寫,即我們所說的比較交換。cas 操作包含三個運算元 —— 記憶體位置(v)、預期原值(a)和新值(b)。如果記憶體位址裡面的值和a的值是一樣的,那麼就將記憶體裡面的值更新成b。cas是通過無限迴圈來獲取資料的,若果在第一輪迴圈中,a執行緒獲取位址裡面的值被b執行緒修改了,那麼a執行緒需要自旋,到下次迴圈才有可能機會執行。

node:jdk8中徹底放棄了segment轉而採用的是node(儲存key,value及key的hash值的資料結構。其中value和next都用volatile修飾,保證併發的可見性。),其設計思想也不再是jdk1.7中的分段鎖思想。

class nodeimplements map.entry
紅黑樹:在jdk8中concurrenthashmap的結構,由於引入了紅黑樹,使得concurrenthashmap的實現非常複雜,我們都知道,紅黑樹是一種效能非常好的二叉查詢樹,其查詢效能為o(logn),但是其實現過程也非常複雜,而且可讀性也非常差。

總結:

jdk1.8版本中synchronized+cas+hashentry+紅黑樹

azkaban web server原始碼解析

azkaban主要用於hadoop相關job任務的排程,但也可以應用任何需要排程管理的任務,可以完全代替crontab。azkaban主要分為web server 任務上傳,管理,排程 executor server 接受web server的排程指令,進行任務執行 1.資料表 projects 工...

JDK LinkedHashMap原始碼解析

今天來分析一下jdk linkedhashmap的源 public class linkedhashmapextends hashmapimplements map可以看到,linkedhashmap繼承自hashmap,並且也實現了map介面,所以linkedhashmap沿用了hashmap的大...

Redux原始碼createStore解讀常用方法

const store createstore reducer,preloadedstate enhancer 直接返回當前currentstate,獲取state值,return state 我覺得應該深轉殖乙個新的物件返回,不然有可能會被外部修改 function getstate consol...