Java併發之ConcurrentHashMap詳解

一、ConcurrentHashMap是什麼?

      ConcurrentHashMap是線程安全的併發容器,是用來替代在多線程環境下的HashMap,因爲HashMap是線程不安全的,多線程環境下put操作可能會導致死循環,CPU利用率上升到100%。雖然有同步容器Hashtable和Collections.synchronizedMap方法使得容器同步,但是這些容器效率都非常低,因爲它們鎖的是整個容器,而ConcurrentHashMap採用的是分段鎖,將同一個容器的劃分爲好多段,某個線程執行某些操作只會獲取一個段的鎖,而不會影響其他線程獲取其他鎖的段。

二、ConcurrentHashMap的結構。

       ConcurrentHashMap把整個容器很爲許多個Segment(段),段數就是併發度,每個Segment類似於一個Hashtable,管理一個HashEntry數組,每個HashEntry是一個鏈表頭,或者紅黑樹的根,其實Segment的數據結構類似於HashMap,學過HashMap的底層原理就更加容易理解ConcurrentHashMap,HashMap原理講解鏈接點擊打開鏈接

        分段鎖具體體現在哪裏?

        Segment繼承ReentrantLock,這樣就很容易對每個Segment加鎖了。類似於get或remove這些操作,都只需要在操作前對一個Segment加鎖。但是有些操作需要跨段,比如size()、containsValue()和isEmpty()方法,因此爲了保證併發效率,允許size返回的是一個近似值而不是精確值。ConcurrentHashMap提供的迭代器不會拋出ConcurrentModificationException,因此不需要在迭代過程中對容器加鎖。即迭代器具有弱一致性,而非及時失敗。弱一致性的迭代器可以容忍併發的修改,當創建迭代器時會遍歷已有的元素,可以但不保證在迭代器被構造後將修改操作反映給容器。


                                    (圖片來自網絡)

三、核心操作

1、哈希定位操作。

(1)首先對key進行hash運算,得到的值爲h1。即h1 = hash(key)。

(2)對h1的高几位進行hash操作,得到的值幾位Segment所在的位置。h2 = hash(h1高位)

(3)對h1進行hash操作,得到的值即爲該Segment中HashEntry所在的位置。h3 = hash(h1)

2、size()操作。

(1)在不對任何Segment加鎖的情況下,遍歷每個Segment,並且求和,如果三次中有相鄰兩次求得的每個Segment都相等,那麼說明在這兩次期間,每個Segment都沒有被更新,那麼可以直接返回size。

(2)若三次都不相等,那麼就全部加鎖,求和。

四、注意

1、key和value都不能爲null。

2、雖然ConcurrentHashMap是線程安全的,但不保證所有操作都是線程安全的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章