在1.7及以前,使用hashmap進行put操作時,當元素超過閾值時,會觸發resize操作,這時候可能就會出現死迴圈的情況,導致cpu佔用率達到100%。
首先,我們要先了解hashmap的資料結構,hashmap的主幹是乙個entry陣列。entry是hashmap的基本組成單元,每乙個entry包含乙個key-value鍵值對。(其實就是乙個陣列,陣列儲存著單向鍊錶的表頭)
當存在hash衝突時,就會把新元素加入到鍊錶中,而這一步就是出現死迴圈的關鍵,jdk 1.7及以前,會被新元素插入到頭部,因此才可能產生死迴圈。
由於死迴圈是在進行put操作時產生的,所以先看put方法。
public v put
(k key, v value)
} modcount++
;//該key不存在,需要增加乙個結點
addentry
(hash, key, value, i)
;return null;
}
當要新增乙個新的節點時,就會去判斷是否超過閾值,也就是在addentry中。
void
addentry
(int hash, k key, v value,
int bucketindex)
resize時,會把table(陣列)空間擴大一倍,因為陣列變大,hash值計算會有所不同,所以原本的資料要進行轉移,重新hash。
void
resize
(int newcapacity)
transfer方法就是出現問題的關鍵位置。
void
transfer
(entry[
] newtable)
while
(e != null);}
}}
正常情況下,這段**是不會出錯的。
而執行緒b在獲得cpu使用權之後,執行完了一整個流程**,所以此時hashmap中的陣列及鍊錶結構如下,看清楚圖中紅色部分,也就是說執行緒a中的e
仍然指向key:3
,next
仍然指向key:7
。
此時,執行緒a被排程回來執行。
do
while
(e != null)
;
執行e.next = newtable[i];
,因為e為key:3
,此時newtable[i]
是key:7
,因此key:3
會指向key:7
,如圖所示。
執行newtable[i] = e
,陣列3會指向key:3
。
那麼這是,環形已經形成。
執行e = next;
永遠會在key:3
與key:7
中迴圈。
HashMap多執行緒下發生死迴圈的原因
由於在公司專案中偶爾會遇到hashmap死迴圈造成cpu100 重啟後問題消失,隔一段時間又會反覆出現。今天在這裡來仔細剖析下多執行緒情況下hashmap所帶來的問題 1 多執行緒put操作後,get操作導致死迴圈。2 多執行緒put非null元素後,get操作得到null值。3 多執行緒put操作...
HashMap 多執行緒 死迴圈 Java
hashmap,眾所周知,是執行緒不安全的。在多執行緒的情況下,在get 非常有可能出現死迴圈。因為 hashmap採用鍊錶解決hash衝突,因為是鍊錶結構,那麼就很容易形成閉合的鏈路,這樣在迴圈的時候只要有執行緒對這個hashmap進行get操作就會產生死迴圈。只 有乙個執行緒對hashmap的資...
多執行緒併發產生的原因
背景 先看下面一段 看看執行結果 class program public class accounttest 有乙個accounttest類,類裡面有乙個account值,有乙個add方法功能是把account值累加100萬次 main方法裡面開啟了兩個任務,兩個任務共用乙個accounttest...