java併發:併發容器之ConcurrentHashMap
初識ConcurrentHashMap
針對併發容器中的ConcurrentHashMap,《java併發程式設計實戰》一書有如下這樣一段文字:
此處將揭開ConcurrentHashMap的神祕面紗,首先我們看一下ConcurrentHashMap的結構圖,如下:
詳述ConcurrentHashMap
ConcurrentHashMap的併發度
ConcurrentHashMap把實際map劃分成若干部分來實現它的可擴充套件性和執行緒安全。這種劃分是使用併發度獲得的,它是ConcurrentHashMap類建構函式的一個可選引數,預設值為16,這樣在多執行緒情況下就能避免爭用。
ConcurrentHashMap的鎖分離技術
HashTable容器在競爭激烈的併發環境下效率低下,原因是所有訪問HashTable的執行緒都必須競爭同一把鎖。若容器中有多把鎖,每一把鎖用於鎖定容器其中一部分資料,那麼當多執行緒訪問容器裡不同資料段的資料時,執行緒間就不會存在鎖競爭,從而可以有效提高併發訪問效率,這就是ConcurrentHashMap所使用的鎖分段技術,首先將資料分成一段一段的儲存,然後給每一段資料配一把鎖,當一個執行緒佔用鎖並訪問其中一個段資料的時候,其他段的資料也能被其他執行緒訪問。
對比上圖(該圖摘自網路),同步容器HashTable實現鎖的方式是鎖整個hash表,而併發容器ConcurrentHashMap的實現方式是鎖桶(
ConcurrentHashMap將hash表分為16個桶(預設值),諸如get,put,remove等常用操作只鎖當前需要用到的桶。試想,原來只能一個執行緒進入,現在卻能同時16個執行緒進入,併發性的提升是顯而易見的。
ConcurrentHashMap的remove操作
當對ConcurrentHashMap進行remove操作時,並不是進行簡單的節點刪除操作
對比上圖,當對ConcurrentHashMap的一個segment(也就是一個桶中的節點)進行remove後,例如,刪除節點C,C節點實際並沒有被銷燬,而是將C節點前面的反轉並拷貝到新的連結串列中,C節點後面的不需要被克隆。這樣的操作使併發的讀執行緒不受併發的寫執行緒的干擾,例如,現在有一個讀執行緒讀到了A節點,寫執行緒把C刪掉了,但是看上圖,讀執行緒仍然可以繼續讀下去;當然,如果在刪除C之前讀執行緒讀到的是D,那麼更不會有影響。
根據上面所提到的在ConcurrentHashMap中刪除一個節點並不會立刻被讀執行緒感受到的效果,就是傳說中的弱一致性,所以ConcurrentHashMap的迭代器是弱一致性迭代器