HashMap 和 ConcurrentHashMap 的區別?


HashMap 和 ConcurrentHashMap 的區別?

jdk1.8之前,ConcurrentHashMap 採用Segment + HashEntry的方式進行實現,該類包含兩個靜態內部類 HashEntry 和 Segment ;前者用來封裝映射表的鍵值對,後者用來充當鎖的角色; Segment 是一種可重入的鎖 ReentrantLock,每個 Segment 守護一個HashEntry 數組裡得元素,當對 HashEntry 數組的數據進行修改時,必須首先獲得對應的 Segment 鎖,相對 於Hashtable 的 syncrhronized 關鍵字鎖的粒度更精細了一些,併發性能更好。而 HashMap 沒有鎖機制,不是線程安全的。
JDK8 之後,ConcurrentHashMap 放棄了Segment臃腫的設計,取而代之的是採用Node + CAS + Synchronized來保證併發安全進行實現。直接採用transient volatile Node[] table保存數據,採用table數組元素作為鎖,從而實現了對每一行數據進行加鎖,進一步減少併發衝突的概率。
改進二:將原先table數組+單向鏈表的數據結構,變更為table數組+單向鏈表+紅黑樹的結構。對於hash表來說,最核心的能力在於將key hash之後能均勻的分佈在數組中。如果hash之後散列的很均勻,那麼table數組中的每個隊列長度主要為0或者1。但實際情況並非總是如此理想,雖然ConcurrentHashMap類默認的加載因子為0.75,但是在數據量過大或者運氣不佳的情況下,還是會存在一些隊列長度過長的情況,如果還是採用單向列表方式,那麼查詢某個節點的時間複雜度為O(n);因此,對於個數超過8(默認值)的列表,jdk1.8中採用了紅黑樹的結構,那麼查詢的時間複雜度可以降低到O(logN),可以改進性能。


2、HashMap 的鍵值對允許有 null ,但是 ConCurrentHashMap 都不允許。


分享到:


相關文章: