ConcurrentHashMap源碼閱讀筆記(JUC)

76-85行 註釋:這裏主要講的是同爲線程安全的Hash,HashTable和ConcurrentHashMap的區別。ConcurrentHashMap(下文用本類指代)雖然是線程安全的,但是檢索操作(比如get,是不保證加以鎖的),並且本類沒有任何操作用於鎖住整個類實例的表。本類並不是以同步鎖(synchronize)來保證線程安全的,而是它本身操作的性質(CAS無鎖化同步)。


87行-106行 註釋:因爲前面提到本類中的檢索操作是不加互斥鎖的,所以可能在讀操作的時候會與寫操作(put/remove)發生重疊(即在多線程情況下出現的)。這時候檢索的結果應該是最近一次寫操作完成後的結果。而在大多數情況下,寫操作應該是比讀操作先完成的(筆者猜想可能是優先級的問題。)而在大批量操作(比如putAll/clear/size/isEmpty/containsValue),併發執行get方法得到的是插入/刪除節點一部分鍵值對,因此上述操作只有在單線程情況下能保證正確,否則只能代表多線程情況下的瞬時狀態。僅供參考作爲評估,而不應該用於程序的控制。同樣的,在大批量操作的情況下創建的迭代器/字符分割器/枚舉器,反應的結果是創建迭代器時hash表的狀態。注意,本類不迭代器並不拋出快速失敗異常。

解析:(1)本類的迭代器不拋出“快速失敗”異常。(2)聚集類操作(putAll/clear/size/isEmpty/containsValue)在多線程情況下得到的可能是本類對應一部分的結果。


108-128行 註釋:這裏和前面記錄的hashmap就很像了。首先是介紹了一下初始容量和裝載因子,以及它們的作用。由於我們知道resize/rehash操作是消耗很大的,應該儘量避免這種操作。對於實現了Compareable接口的類,會採用compareTo方法進行比較保證有序。還提到了以前JDK版本本類方法中提供一種參數的構造函數concurrencyLevel指定鎖段長度(最大65535)

解析:在JDK 1.7的時候,通過的不是CAS而是鎖段,來執行操作。這是1.8和1.7的最大的一個區別。這也是爲什麼hashtable基本不使用,都使用本類的原因。

鎖分段技術HashTable在競爭激烈的併發環境下表現出效率低下的原因是所有訪問HashTable的線程都必須競爭同一把鎖,假如容器裏有多把鎖,每一把鎖用於鎖容器其中一部分的數據,那麼當多線程訪問容器裏不同數據段的數據時,線程間就不會存在鎖競爭,從而可以有效提高併發訪問效率,這就是ConcurrentHashMap所使用的鎖分段技術.首先將數據分成一段一段地存儲,然後給每一段數據配一把鎖,當一個線程佔用鎖訪問其中一個段數據的時候,其他段的數據也能被其他線程訪問.

同時,本類也可以用作數據庫緩存(類似於Redis),只是本類主要是用在短時間訪問量高的情況,map可以作爲內存式緩存,短時間訪問量高可以使用

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