高并发下HashMap死锁问题:源码级解析与循环链表的诞生
引言:HashMap的“致命陷阱”
HashMap是Java中使用最频繁的数据结构之一,但在高并发场景下,它却隐藏着一个危险的“陷阱”——多线程扩容死锁。这种问题会导致CPU占用率飙升,程序陷入“假死”状态。本文将通过源码解析+场景推演,带你彻底理解死锁成因,并给出解决方案。
一、HashMap扩容机制与再哈希
1.1 扩容触发条件
当HashMap中元素数量超过阈值 = 容量 × 负载因子
(默认0.75)时,触发扩容,容量翻倍。
1.2 再哈希与链表拆分
扩容时,旧链表的节点会根据哈希值的高位差异((e.hash & oldCap) == 0
)拆分为低位链表和高位链表,分别挂载到新数组的j
和j + oldCap
位置。这是JDK8的优化,减少哈希碰撞概率。
// HashMap#resize() 核心代码片段
Node<K,V> loHead = null, loTail = null; // 低位链表头尾指针
Node<K,V> hiHead = null, hiTail = null; // 高位链表头尾指针
do {
next = e.next; // 记录下一个节点
if ((e