26

正如许多人指出并遇到的那样,在HashMap.put同时使用时可能会进入无限执行循环(请参阅GRIZZLY-1207JGRP-525、可能是HHH-6414和这个 SO答案)。

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

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

4

1 回答 1

34

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

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

void resize(int newCapacity);问题是和实现的方式造成的void transfer(Entry[] newTable);,大家可以自己看下openjdk源码。运气不好,时机很好,条目被颠倒(在这个数据结构中不需要排序),最终导致在线程继续运行时错误地相互引用while(e != null)......

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

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

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

于 2012-12-04T04:28:02.543 回答