1.7和1.8中的ConCurrentHashMap對比

1.71.8中的ConCurrentHashMap對比

1.7

數據結構

jdk1.7中採用Segment + HashEntry的方式進行實現,

 

初始化

ConcurrentHashMap初始化時,計算出Segment數組的大小ssize和每個SegmentHashEntry數組的大小cap,並初始化Segment數組的第一個元素;其中ssize大小爲2的冪次方,默認爲16cap大小也是2的冪次方,最小值爲2,最終結果根據根據初始化容量initialCapacity進行計算。其中Segment在實現上繼承了ReentrantLock,這樣就自帶了鎖的功能

Put實現

當執行put方法插入數據時,根據keyhash值,在Segment數組中找到相應的位置,如果相應位置的Segment還未初始化,則通過CAS進行賦值,接着執行Segment對象的put方法通過加鎖機制插入數據,實現如下:

場景:線程A和線程B同時執行相同Segment對象的put方法

線程A執行tryLock()方法成功獲取鎖,則把HashEntry對象插入到相應的位置;

線程B獲取鎖失敗,則執行scanAndLockForPut()方法,在scanAndLockForPut方法中,會通過重複執行tryLock()方法嘗試獲取鎖,在多處理器環境下,重複次數爲64,單處理器重複次數爲1,當執行tryLock()方法的次數超過上限時,則執行lock()方法掛起線程B

當線程A執行完插入操作時,會通過unlock()方法釋放鎖,接着喚醒線程B繼續執行;

size實現

因爲ConcurrentHashMap是可以併發插入數據的,所以在準確計算元素時存在一定的難度,一般的思路是統計每個Segment對象中的元素個數,然後進行累加,但是這種方式計算出來的結果並不一樣的準確的,因爲在計算後面幾個Segment的元素個數時,已經計算過的Segment同時可能有數據的插入或則刪除,在1.7的實現中,採用瞭如下方式:

先採用不加鎖的方式,連續計算元素的個數,最多計算3次:

如果前後兩次計算結果相同,則說明計算出來的元素個數是準確的;

如果前後兩次計算結果都不同,則給每個Segment進行加鎖,再計算一次元素的個數;

1.8

數據結構

1.8中放棄了Segment臃腫的設計,取而代之的是採用Node + CAS + Synchronized來保證併發安全進行實現

 

 

 

只有在執行第一次put方法時纔會調用initTable()初始化Node數組

put實現

當執行put方法插入數據時,根據keyhash值,在Node數組中找到相應的位置,實現如下:

1、如果相應位置的Node還未初始化,則通過CAS插入相應的數據;

2、如果相應位置的Node不爲空,且當前該節點不處於移動狀態,則對該節點加synchronized鎖,如果該節點的hash不小於0,則遍歷鏈表更新節點或插入新節點;

3、如果該節點是TreeBin類型的節點,說明是紅黑樹結構,則通過putTreeVal方法往紅黑樹中插入節點;

4、如果binCount不爲0,說明put操作對數據產生了影響,如果當前鏈表的個數達到8個,則通過treeifyBin方法轉化爲紅黑樹,如果oldVal不爲空,說明是一次更新操作,沒有對元素個數產生影響,則直接返回舊值;

5、如果插入的是一個新節點,則執行addCount()方法嘗試更新元素個數baseCount

size實現

1.8中使用一個volatile類型的變量baseCount記錄元素的個數,當插入新數據或則刪除數據時,會通過addCount()方法更新baseCount

1、初始化時counterCells爲空,在併發量很高時,如果存在兩個線程同時執行CAS修改baseCount值,則失敗的線程會繼續執行方法體中的邏輯,使用CounterCell記錄元素個數的變化;

2、如果CounterCell數組counterCells爲空,調用fullAddCount()方法進行初始化,並插入對應的記錄數,通過CAS設置cellsBusy字段,只有設置成功的線程才能初始化CounterCell數組

3、如果通過CAS設置cellsBusy字段失敗的話,則繼續嘗試通過CAS修改baseCount字段,如果修改baseCount字段成功的話,就退出循環,否則繼續循環插入CounterCell對象;

所以在1.8中的size實現比1.7簡單多,因爲元素個數保存baseCount中,部分元素的變化個數保存在CounterCell數組中,通過累加baseCountCounterCell數組中的數量,即可得到元素的總個數。

 

 

發佈了37 篇原創文章 · 獲贊 17 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章