JDK1.7的HashMap的环形链表

分析扩容的核心代码

java 复制代码
// 构建新数组
Entry[] newTable = new Entry[newCapacity];
// 迁移老数组数据到新数组
transfer(newTable, initHashSeedAsNeeded(newCapacity));
// 迁移完毕后,替换老数组
table = newTable;
java 复制代码
// 迁移数据的过程
void transfer(Entry[] newTable, boolean rehash){
    int newCapacity = newTable.length;
    // 外层遍历数组
    for (Entry<k,v> e:table){
        // 遍历链表
        // 2号线程走完第二次循环,完成迁移数据(如下图2所示)
        // 1号线程走完第二次循环,发现指向的是A(如下图3所示)
        // 1号线程走完第三次循环,完成迁移数据(如下图4所示)
        while(null != e){
            Entry<K,V> next = e.next;
            // 1号线程执行到这里停止
            if(rehash){
                e.hash = null == e.key ? 0 : hash(e.key)
            }
            int i = indexFor(e.hash, newCapacity);
            e.next = newTable[i];
            newTable[i] = e;
            e = next;
        }
    }
}

图1
图2
图3
图4

JDK1.7中的HashMap是线程不安全的,可能会出现并发扩容的操作。

JDK1.7中的HashMap在迁移数据时,采用的是头插法,导致节点的next指针会有变化。

先迁移完的线程,可能会导致其他线程在扩容时,扩容到最后,将最开始的节点重新的插入到了头节点的位置,导致指针再次变化,从而形成了一个环形链表。

相关推荐
郑州光合科技余经理几秒前
本地生活服务系统:预约状态和进度通知接口怎么拆
java·开发语言·前端·javascript·后端·php·生活
靠沿4 分钟前
MySQL数据库基础——事务
java·数据库·mysql
蒲公英eric6 分钟前
线性回归与正则化:从最小二乘到岭回归、LASSO
人工智能·算法·数学建模·线性回归·岭回归·最小二乘·lasso
碧海银沙音频科技研究院4 小时前
炬芯ATS3089X手表的HFP通话不自动路由到设备BT的问题解决
网络·人工智能·嵌入式硬件·算法
Joy T6 小时前
Agent 确定性上下文设计:从 Prompt 参数注入到能力分层
java·开发语言·微服务·架构·prompt·agent context
m0_587383009 小时前
广州 24 小时自助健身房解决方案技术实现与实战指南
java·spring·小程序·架构·需求分析
mmmmath_39 小时前
LeetCode.199.二叉树的右视图
数据结构·leetcode
·云扬·9 小时前
Prompt 工程与安全:从 System 设计到注入防御
java·人工智能·安全·ai·prompt
专注仿真9 小时前
引擎扩展性与集成设计深度剖析:从 14 个扩展点到 DIS→HLA 演进之路
开发语言·算法·仿真引擎·推演引擎