博客 / 詳情

返回

談談HashMap的一些問題

hashMap在多線程環境下的表現

  • 在jdk1.7中多線程put時可能會導致get無限循環,具體表現為CPU使用率100%;

該方法實現的機制就是將每個鏈表轉化到新鏈表,並且鏈表中的位置發生反轉,而這在多線程情況下是很容易造成鏈表迴路,從而發生 get() 死循環。所以只要保證建新鏈時還是按照原來的順序的話就不會產生循環(JDK 8 的改進)。即在jdk1.7是採用的頭插法,在jdk1.8使用了尾插法解決。

HashMap死循環只發生在JDK1.7版本中,主要原因是JDK1.7中的HashMap,在頭插法 加 鏈表 加 多線程併發 加 擴容這幾個情形累加到一起就會形成死循環。多線程環境下建議採用ConcurrentHashMap替代。

  • 多線程put時可能導致元素丟失 原因:當多個線程同時執行addEntry(hash,key ,value,i)時,如果產生哈希碰撞,導致兩個線程得到同樣的bucketIndex去存儲,就可能會發生元素覆蓋丟失的情況

Hashmap中的鏈表大小超過八個時會自動轉化為紅黑樹,當刪除小於六時重新變為鏈表,為啥呢?

根據泊松分佈,在負載因子默認為0.75的時候,單個hash槽內元素個數為8的概率小於百萬分之一,所以將7作為一個分水嶺,等於7的時候不轉換,大於等於8的時候才進行轉換,小於等於6的時候就化為鏈表。 避免樹和鏈表的頻繁轉換

從時間複雜度分析,樹的查詢時間複雜度是logn,所於大於等於8使用紅黑樹。

Collections.synchronizedMap是怎麼實現線程安全的

在SynchronizedMap內部維護了一個普通對象Map,還有排斥鎖mutex,如圖

image.png

我們在調用這個方法的時候就需要傳入一個Map,可以看到有兩個構造器,如果你傳入了mutex參數,則將對象排斥鎖賦值為傳入的對象。

如果沒有,則將對象排斥鎖賦值為this,即調用synchronizedMap的對象,就是上面的Map。

創建出synchronizedMap之後,再操作map的時候,就會對方法上鎖。

user avatar dm2box 頭像 mo_or 頭像 lingfeng23 頭像 redorblack 頭像 nian_5aedc008c1353 頭像 91cyz 頭像 tengteng_5c7902af4b01e 頭像 qiehxb8 頭像 luoshenshen 頭像 mysteryjack 頭像 yexiaobai_616e2b70869ae 頭像 willliaowh 頭像
12 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.