1. 程式人生 > 其它 >java併發:併發容器之ConcurrentHashMap

java併發:併發容器之ConcurrentHashMap

初識ConcurrentHashMap

針對併發容器中的ConcurrentHashMap,《java併發程式設計實戰》一書有如下這樣一段文字:

此處將揭開ConcurrentHashMap的神祕面紗,首先我們看一下ConcurrentHashMap的結構圖,如下:

詳述ConcurrentHashMap

ConcurrentHashMap的併發度

  ConcurrentHashMap把實際map劃分成若干部分來實現它的可擴充套件性和執行緒安全。這種劃分是使用併發度獲得的,它是ConcurrentHashMap類建構函式的一個可選引數,預設值為16,這樣在多執行緒情況下就能避免爭用。

ConcurrentHashMap的鎖分離技術

  HashTable容器在競爭激烈的併發環境下效率低下,原因是所有訪問HashTable的執行緒都必須競爭同一把鎖。若容器中有多把鎖,每一把鎖用於鎖定容器其中一部分資料,那麼當多執行緒訪問容器裡不同資料段的資料時,執行緒間就不會存在鎖競爭,從而可以有效提高併發訪問效率,這就是ConcurrentHashMap所使用的鎖分段技術,首先將資料分成一段一段的儲存,然後給每一段資料配一把鎖,當一個執行緒佔用鎖並訪問其中一個段資料的時候,其他段的資料也能被其他執行緒訪問。

  對比上圖(該圖摘自網路),同步容器HashTable實現鎖的方式是鎖整個hash表,而併發容器ConcurrentHashMap的實現方式是鎖桶(

簡單理解就是將整個hash表想象成一大缸水,現在將這大缸裡的水分到了幾個水桶裡,hashTable每次都鎖定這個大缸,而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的迭代器是弱一致性迭代器