ConcurrentHashMap面試題


 

1.JDK1.7版本的CurrentHashMap的實現原理

在JDK1.7中ConcurrentHashMap采用了數組+Segment+分段鎖的方式實現。

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的並發能力可以大大的提高。

2.JDK1.8版本的CurrentHashMap的實現原理

JDK8中ConcurrentHashMap參考了JDK8 HashMap的實現,采用了數組+鏈表+紅黑樹的實現方式來設計,內部大量采用CAS操作,這里我簡要介紹下CAS。

CAS是compare and swap的縮寫,即我們所說的比較交換。cas是一種基於鎖的操作,而且是樂觀鎖。在java中鎖分為樂觀鎖和悲觀鎖。悲觀鎖是將資源鎖住,等一個之前獲得鎖的線程釋放鎖之后,下一個線程才可以訪問。而樂觀鎖采取了一種寬泛的態度,通過某種方式不加鎖來處理資源,比如通過給記錄加version來獲取數據,性能較悲觀鎖有很大的提高。

CAS 操作包含三個操作數 —— 內存位置(V)、預期原值(A)和新值(B)。如果內存地址里面的值和A的值是一樣的,那么就將內存里面的值更新成B。CAS是通過無限循環來獲取數據的,若果在第一輪循環中,a線程獲取地址里面的值被b線程修改了,那么a線程需要自旋,到下次循環才有可能機會執行。

JDK8中徹底放棄了Segment轉而采用的是Node,其設計思想也不再是JDK1.7中的分段鎖思想。

Node:保存key,value及key的hash值的數據結構。其中value和next都用volatile修飾,保證並發的可見性。

Java8 ConcurrentHashMap結構基本上和Java8的HashMap一樣,不過保證線程安全性。

在JDK8中ConcurrentHashMap的結構,由於引入了紅黑樹,使得ConcurrentHashMap的實現非常復雜,我們都知道,紅黑樹是一種性能非常好的二叉查找樹,其查找性能為O(logN),但是其實現過程也非常復雜,而且可讀性也非常差,DougLea的思維能力確實不是一般人能比的,早期完全采用鏈表結構時Map的查找時間復雜度為O(N),JDK8中ConcurrentHashMap在鏈表的長度大於某個閾值的時候會將鏈表轉換成紅黑樹進一步提高其查找性能。

總結

其實可以看出JDK1.8版本的ConcurrentHashMap的數據結構已經接近HashMap,相對而言,ConcurrentHashMap只是增加了同步的操作來控制並發,從JDK1.7版本的ReentrantLock+Segment+HashEntry,到JDK1.8版本中synchronized+CAS+HashEntry+紅黑樹。

1.數據結構:取消了Segment分段鎖的數據結構,取而代之的是數組+鏈表+紅黑樹的結構。

2.保證線程安全機制:JDK1.7采用segment的分段鎖機制實現線程安全,其中segment繼承自ReentrantLock。JDK1.8采用CAS+Synchronized保證線程安全。

3.鎖的粒度:原來是對需要進行數據操作的Segment加鎖,現調整為對每個數組元素加鎖(Node)。

4.鏈表轉化為紅黑樹:定位結點的hash算法簡化會帶來弊端,Hash沖突加劇,因此在鏈表節點數量大於8時,會將鏈表轉化為紅黑樹進行存儲。

5.查詢時間復雜度:從原來的遍歷鏈表O(n),變成遍歷紅黑樹O(logN)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM