2012-12-04 62 views
23

由於一些人已經注意到並遇到HashMap.put可以進入同時使用時,一個無限循環執行(見GRIZZLY-1207JGRP-525,可能HHH-6414,而這SO answer )。解釋造成HashMap.put時機()來執行一個無限循環

HashMap明確記錄爲非線程安全。顯然,正確的解決方案是特別使用Map,ConncurrentHashMap的線程安全實現。我更加好奇導致無限循環的併發時序。我最近用Java 7 JRE遇到了這個循環,並想了解確切的原因。例如,這是由多個投入同時引起的嗎?

HashMap.put裏面的內容顯示HashMap.Entry包含到下一個節點的鏈接(在存儲桶中?)。我認爲這些鏈接越來越腐敗,包含循環引用,這是導致無限循環。但是,我仍然不清楚腐敗是如何發生的。

回答

29

與許多人認爲的相反,multi-threadingHashMaps的主要問題不僅僅是重複的條目或消失的條目......正如您所說的,當兩個或多個Threads同時決定調整HashMap

如果HashMap的大小通過一個給定的閾值,幾個線程可能最終試圖同時調整它的大小,如果我們足夠幸運(您已經在生產環境中部署了代碼),它們會一直持續下去。 ..

該問題是由void resize(int newCapacity);void transfer(Entry[] newTable);執行方式引起的,您可以自己查看一下openjdk source code。混亂的運氣,好的時機,反過來的條目(在這個數據結構中不需要排序),並且最終錯誤地指向對方,而線程繼續運行while(e != null) ...

雖然我可以嘗試給我一個自己的解釋,我想給Paul Tyma的職位(我不能比他做得更好)的學分,在那裏我學會了如何這第一次工作,我決定找出我爲什麼不被僱傭幾個工作幾個月前...

http://mailinator.blogspot.com/2009/06/beautiful-race-condition.html

正如保羅說,最好的詞來形容這場比賽是條件是:beautiful