置顶 精华 提问已解决 HashMap 在多线程下 put 导致死循环,具体是什么原理?

Java SE/EE 1454 浏览 4 回复 2026-09-09 23:12 悬赏 50 积分
👍143
⭐收藏
编程小白鸭 楼主 Lv3 ・韩国
2026-09-09 23:12 1454 阅读 4 回复

看面经看到 JDK7 的 HashMap 并发 put 会导致 CPU 100%,一直没搞懂为什么扩容会产生环形链表。

有没有大佬能画个图讲讲?最好能说说 JDK8 之后为什么修复了。

Java SE/EE 置顶 精华 提问 悬赏 50
回复 👍 45
全部回复 4 条

核心是 JDK7 扩容用的头插法,多线程同时 resize 时,节点 A.next = B 和 B.next = A 可能同时发生,形成环。

JDK8 改成尾插法 + 高位拆分,保持了原有顺序,所以不会出现环形链表。但 JDK8 的 HashMap 仍然不是线程安全的,会丢数据,并发场景请用 ConcurrentHashMap。

Lv8 2026-09-09 23:41 2 楼
回复 👍 33
DBA老赵 ・印度

补充一张图(文字版):

扩容前:A -> B -> null\n线程1 挂起时:B -> A\n线程2 完成后:A -> B -> A (成环)

遍历到这个桶就是死循环。

Lv7 2026-09-10 02:28 3 楼
回复 👍 59
编程小白鸭 最佳答案 ・韩国

明白了!感谢两位,那 ConcurrentHashMap 在 JDK8 中是怎么保证安全的?

Lv3 2026-09-10 05:31 4 楼
回复 👍 80

JDK8 的 CHM 用 synchronized 锁住单个桶的头节点 + CAS 插入,锁粒度从 Segment 降到桶级别,并发度更高。

Lv8 2026-09-10 02:58 5 楼
回复 👍 78
发表回复
登录 后参与回复