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

2022-09-01 17:27:55

正如许多人已经注意到和遇到的那样,当同时使用时可以进入无限的执行循环(参见GRIZZLY-1207JGRP-525,可能是HHH-6414,以及这个SO答案)。HashMap.put

HashMap被清楚地记录为非线程安全。显然,正确的解决方法是使用 的线程安全实现,特别是。我对导致无限循环的并发时序感到好奇。我最近在Java 7 JRE上遇到了这个循环,并希望了解确切的原因。例如,这是由同时进行多个看跌期权引起的吗?MapConncurrentHashMap

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


答案 1

与许多人的想法相反,和的主要问题不仅仅是重复的条目或消失的条目......正如您所说,当两个或多个同时决定调整 .multi-threadingHashMapsThreadsHashMap

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

问题是由 和 实现的方式引起的,您可以自己查看 openjdk 源代码。运气不好,时机好,条目被反转(在此数据结构中不需要排序),并且最终在线程继续运行时错误地相互引用......void resize(int newCapacity);void transfer(Entry[] newTable);while(e != null)

虽然我可以尝试自己给你一个解释,但我想感谢Paul Tyma的帖子(无论如何我都不能比他做得更好),在那里我第一次决定弄清楚为什么几个月前我没有被雇用来工作时,我了解了这是如何工作的......

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

正如保罗所说,用最好的词来形容这场竞赛是条件:beautiful


答案 2

推荐