4.5.1HashMap死循環分析

注:源圖和總結來自享學課堂,自己消化之後略有補充修改

備註:基於1.7jdk進行分析

備註2:強烈建議自己跟着步驟一個圖一個圖手動畫,理解深刻一點也快一點

簡介

在多線程之下,在put操作的時候,會導致HashMap的Entry鏈表死循環,導致CPU利用率接近100%

單線程下HashMap的擴容

原理

擴容只要有三個方法:

AddEntry

resize

transfer

擴容總結

1、擴容2倍

2、新建數組,容量是以前的2倍

3、輪詢oldtable上的值,計算在newtable中的位置,採用頭插法以鏈表形式連接

實例

有如下的hashMap

按照代碼中的方法,移動如下

第一次:

第二次:

第三次:

併發下的擴容

初始值:

線程1剛執行完Entry<K,V> next = e.next;就被阻塞了,線程2已經完成了所有的擴擴容操作,剛執行完Entry<K,V> next = e.next;,只剩下e.next = newTable[3] ; newTable[3] = e;  e=next

此時線程的狀態是這個樣子

接下來線程1開始執行newTable[i]=e,即newTable[3]=e

執行e=next

開始新一輪循環

最開始線程2不是還有最後一點沒有執行完嗎e.next = newTable[3] ; newTable[3] = e;  e=next,這個時候線程2完全執行完成

此時執行Entry<key,value> next = e.next;

執行e.next= newTable[3];,newTable[3] =e;

執行e=next;於是e=key(3);

開始新一輪while循環

執行e.next = newTable[i],newTable[i]=e;後,循環鏈表產生

產生循環鏈表之後,一旦線程調用get查找一個不存在的元素是(例如11,15),就會進入死循環,CPU消耗100%

總結:

HashMap的死循環是在併發擴容下發生的,因爲一個線程先進行了擴容變成了倒序鏈表,後一個線程再擴容是,又進行了自己的散列,再次將倒序鏈表變成了正序鏈表,於是形成了一個環形,當get表中不存在的元素是,造成死循環

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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