深入分析ConcurrentHashMap

2021-08-07 14:15:42 字數 1999 閱讀 5562

執行緒不安全的hashmap

因為多執行緒環境下,使用hashmap進行put操作會引起死迴圈,導致cpu利用率接近100%,所以在併發情況下不能使用hashmap。

效率低下的hashtable容器

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

concurrenthashmap的結構:

乙個concurrenthashmap包含乙個segment陣列(segment的結構和hashmap類似,是一種陣列和鍊錶結構);

乙個segment包含乙個hashentry陣列(乙個鍊錶結構的元素)

segment就是鎖:每個segment守護者乙個hashentry陣列裡的元素,當對hashentry陣列的資料進行修改時,必須首先獲得它對應的segment鎖。

concurrenthashmap中主要實體類就是三個:concurrenthashmap(整個hash表),segment(桶),hashentry(節點)

hashentry中,代表每個hash鏈中的乙個節點,就是hashmap中的乙個entry,

除了value不是final外,其餘都為final,這意味著不能從hash鏈的中間或尾部新增或刪除節點,因為這需要修改next 引用值,所有的節點的修改只能從頭部開始。

put操作:可以一律新增到hash鏈的頭部。

remove操作:可能需要從中間刪除乙個節點,這就需要將要刪除節點的前面所有節點整個複製一遍,最後乙個節點指向要刪除結點的下乙個結點。

為了加快定位段以及段中hash槽的速度,每個段hash槽的的個數都是2^n,這使得通過位運算就可以定位段和段中hash槽的位置。

hash槽的的個數不應該是 2^n,這可能導致hash槽分配不均,這需要對hash值重新再hash一次。

(再雜湊,其目的是為了減少雜湊衝突,使元素能夠均勻的分布在不同的segment上,從而提高容器的訪問效率。)

segment中count用來統計該段資料的個數;每次結構改變,即增加或者刪除節點要進行改變;

remove的實現:

整個操作是先定位到段,然後委託給段的remove操作。當多個刪除操作併發進行時,只要它們所在的段不相同,它們就可以同時進行。注意:

第一,當要刪除的結點存在時,刪除的最後一步操作要將count的值減一;

第二,remove執行的開始就將table賦給乙個區域性變數tab;

put的實現:

put操作也是委託給段的put方法

該方法在持有段鎖的情況下進行,要判斷容量是否滿足,不滿足就rehash;

如何擴容。擴容的時候首先會建立乙個兩倍於原容量的陣列,然後將原陣列裡的元素進行再hash後插入到新的陣列裡。為了高效concurrenthashmap不會對整個容器進行擴容,而只對某個segment進行擴容。

get的實現:

直接委託給segment的get方法;

操作不需要鎖,訪問count變數,由於所有的修改操作在進行結構修改時都會在最後一步寫count 變數,通過這種機制保證get操作能夠得到幾乎最新的結構更新。

concurrenthashmap的get操作是如何做到不加鎖的呢?原因是它的get方法裡將要使用的共享變數都定義成volatile,

對於非結構更新,也就是結點值的改變,由於hashentry的value變數是 volatile的,也能保證讀取到最新的值。接下來就是根據hash和key對hash鏈進行遍歷找到要獲取的結點,如果沒有找到,直接訪回null。

IsPostBack深入分析

1 ispostback 介紹 ispostback是 page類有乙個 bool型別的屬性,用來判斷針對當前 form的請求是第一次還是非第一次請求。當 ispostback true時表示非第一次請求,我們稱為 postback,當 ispostback false時表示第一次請求。在 asp....

深入分析ConcurrentHashMap

再多執行緒的情況下,如果使用hashmap,就會導致死迴圈,導致cpu利用率接近100 所以如果是併發的情況不要使用hashmap 導致死迴圈主要是這段 當在多執行緒的情況由於沒有同步導致,著段 在擴容的時候會執行 do while e null 執行緒安全的hashtable 容器 hashtab...

深入分析malloc

本文大量參考了如何實現乙個malloc這篇文章。任何乙個用過或學過c的人對malloc都不會陌生。大家都知道malloc可以分配一段連續的記憶體空間,並且在不再使用時可以通過free釋放掉。但是,許多程式設計師對malloc背後的事情並不熟悉,許多人甚至把malloc當做作業系統所提供的系統呼叫或c...