解释导致HashMap.put()执行无限循环的时间

正如许多人已经注意到并遇到HashMap.put可以在并发使用时进入无限执行循环(参见GRIZZLY-1207 , JGRP-525 ,可能是HHH-6414 ,以及此SO 答案 )。

HashMap明确记录为不是线程安全的。 显然,正确的解决方法是使用MapConncurrentHashMap的线程安全实现。 我对导致无限循环的并发时序更加好奇。 我最近使用Java 7 JRE遇到了这个循环,并希望了解确切的原因。 例如,这是由同时多次看跌引起的吗?

在HashMap.put中查看HashMap.Entry包含指向下一个节点的链接(在存储桶中?)。 我假设这些链接正在腐蚀以包含循环引用,这导致无限循环。 但是,我仍然不明白腐败是如何发生的。

与许多人的想法相反, multi-threadingHashMaps的主要问题不仅仅是重复的条目或消失的……正如你所说,当两个或多个Threads同时决定resize时,可能会发生无限循环HashMap

如果HashMap的大小超过给定的阈值,多个线程最终可能会尝试同时调整它的大小,如果我们足够幸运(你已经在生产中部署了代码),它们将永远继续…

问题是由void resize(int newCapacity);的方式引起的void resize(int newCapacity);void transfer(Entry[] newTable); 实现后,您可以自己查看openjdk源代码 。 运气不好,计时良好,条目反转(在这个数据结构中不需要排序),最终错误地互相引用,而线程一直在进行while(e != null) ……

虽然我可以尝试自己给你一个解释,但我想赞扬Paul Tyma的post(我不能做得比他好)我在那里第一次学会了如何解决这个问题我决定弄清楚为什么我不是几个月前雇用了一份工作……

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

正如保罗所说,描述这场比赛的最佳词语是: beautiful