当前位置: 首页 > article >正文

头插法多线程不可用的原因

为什么头插法多线程下不可用我们以HashMap扩容时用的头插法举例子:JDK 1.7 HashMap 扩容时的头插法迁移逻辑// 旧数组Entry[]oldTabletable;// 新数组容量翻倍Entry[]newTablenewEntry[oldCapacity*2];// 遍历旧数组的每个桶for(inti0;ioldTable.length;i){// 拿到当前桶的头节点eEntryK,VeoldTable[i];// 如果这个桶不为空就遍历链表while(e!null){// 【关键1】先保存e的下一个节点next// 因为接下来要修改e的next指针不保存就会丢失后面的链表EntryK,Vnexte.next;// 【关键2】计算e在新数组中的索引intnewIndexindexFor(e.hash,newTable.length);// 【关键3】头插法把e插入到新数组newIndex位置的链表头部// 步骤1e的next指向新数组当前的头节点e.nextnewTable[newIndex];// 步骤2新数组的头指针指向enewTable[newIndex]e;// 【关键4】处理下一个节点enext;}}// 扩容完成把table指向新数组tablenewTable;一、单线程下头插法迁移的完整演示我们用最简单的例子一步一步看单线程下头插法是如何工作的。初始状态旧数组容量 2桶 0 的链表A → B → null假设 A 和 B 的 hash 值在新数组容量 4中计算出的索引都是 0这样它们会被迁移到同一个桶执行迁移代码步骤第一次循环e Anext e.next→next B保存 A 的下一个节点计算新索引newIndex 0头插法插入 A 到新数组桶 0e.next newTable[0]→A.next null因为新数组桶 0 现在是空的newTable[0] A→ 新数组桶 0A → nulle next→e B准备处理下一个节点当前状态旧数组桶 0A → B → null还没修改新数组桶 0A → null第二次循环e Bnext e.next→next null保存 B 的下一个节点计算新索引newIndex 0头插法插入 B 到新数组桶 0e.next newTable[0]→B.next A新数组桶 0 当前的头是 AnewTable[0] B→ 新数组桶 0B → A → nulle next→e null循环结束最终状态旧数组桶 0A → B → null新数组桶 0B → A → null关键点原来的链表A → B经过头插法迁移后变成了B → A顺序完全反转了。这是头插法最核心的特点也是多线程并发下可能产生死循环的根源。二、多线程下死循环是如何一步步形成的现在我们有了头插法的基础再回头看死循环就会一目了然。场景还是用上面的例子旧数组桶 0 的链表A → B → null两个线程 T1 和 T2 同时扩容。步骤 1T1 执行到一半被挂起T1 开始执行迁移代码执行完第一次循环的第一步EntryK,VeoldTable[i];// e Awhile(e!null){EntryK,Vnexte.next;// next B// 就在这里T1的CPU时间片用完了被挂起// 后面的代码还没执行intnewIndexindexFor(e.hash,newTable.length);...}此时 T1 的栈中保存着e Anext BT1 还没有修改任何节点的 next 指针。步骤 2T2 完整完成了迁移T2 获得 CPU 时间片完整执行了整个迁移过程和我们上面单线程的演示一样。T2 执行完成后T2 的新数组桶 0B → A → null全局的节点指针被修改了B.next AA.next null这是最关键的一步节点是存在于堆内存中的所有线程共享。T2 修改了 A 和 B 的 next 指针T1 对此完全不知情。步骤 3T1 被唤醒继续执行T1 从挂起的地方恢复执行它的栈中还是e Anext BT1 会继续执行它剩下的代码T1 继续执行第一次循环e A// 已经执行过的EntryK,V next e.next; // next BintnewIndexindexFor(e.hash,newTable.length);// newIndex 0// 头插法插入A到T1自己的新数组桶0e.nextnewTable[newIndex];// A.next nullT1的新数组桶0是空的newTable[newIndex]e;// T1的新数组桶0A → nullenext;// e B准备处理下一个节点当前 T1 的状态T1 的新数组桶 0A → nulle BT1 执行第二次循环e BEntryK,Vnexte.next;// 【致命一步】// 现在e是BB的next已经被T2改成了A// 所以 next A而不是我们预期的nullintnewIndexindexFor(e.hash,newTable.length);// newIndex 0// 头插法插入B到T1的新数组桶0e.nextnewTable[newIndex];// B.next AT1的新数组桶0当前头是AnewTable[newIndex]e;// T1的新数组桶0B → A → nullenext;// e A准备处理下一个节点当前 T1 的状态T1 的新数组桶 0B → A → nulle AT1 执行第三次循环e AEntryK,Vnexte.next;// A.next null这个是对的intnewIndexindexFor(e.hash,newTable.length);// newIndex 0// 头插法插入A到T1的新数组桶0e.nextnewTable[newIndex];// A.next BT1的新数组桶0当前头是BnewTable[newIndex]e;// T1的新数组桶0A → B → A → ...enext;// e null循环结束最终结果T1 的新数组桶 0 中链表变成了A → B → A → B → ...一个无限循环的闭环三、为什么 JDK 1.7 要用头插法既然头插法有这么大的问题为什么 JDK 1.7 还要用它性能原因头插法不需要遍历链表找尾部插入速度是 O(1)比尾插法快很多。设计初衷HashMap 本来就不是为多线程环境设计的设计者认为并发场景应该用Hashtable或者ConcurrentHashMap。四、JDK 1.8 的解决方案JDK 1.8 将扩容时的插入方式改为尾插法迁移时会保持链表的原有顺序不会出现反转因此彻底避免了循环引用的产生。再次强调即使 JDK 1.8 解决了死循环问题HashMap 仍然不是线程安全的。多线程环境下仍然会出现数据丢失、覆盖等问题并发场景请务必使用ConcurrentHashMap。

相关文章:

头插法多线程不可用的原因

为什么头插法多线程下不可用?我们以HashMap扩容时用的头插法举例子: JDK 1.7 HashMap 扩容时的头插法迁移逻辑 // 旧数组 Entry[] oldTable table; // 新数组(容量翻倍) Entry[] newTable new Entry[oldCapacity * 2];// 遍历旧数组的每个桶…...

VS Code Copilot Next 配置实战手册(企业级自动化工作流搭建全流程)

更多请点击: https://intelliparadigm.com 第一章:VS Code Copilot Next 自动化工作流配置概览 VS Code Copilot Next 是微软与 GitHub 联合推出的下一代智能编程助手,它深度集成于 VS Code 编辑器中,支持上下文感知的代码生成、…...

视频孪生赋能智慧能源园区:黎阳之光打造全域数智化新标杆

在“双碳”战略与新型电力系统建设加速推进的背景下,能源园区正面临安全管控升级、能效提升压力、协同效率不足三大核心挑战。传统依赖人工巡检、分散系统、经验决策的管理模式,已难以适配现代化能源园区的发展需求。北京黎阳之光科技有限公司作为国内视…...

LLM应用开发模块化工具箱:从设计模式到实战构建智能体

1. 项目概述:一个面向LLM应用开发的模块化工具箱 如果你正在尝试构建基于大语言模型的应用,无论是想做一个能自动处理邮件的智能助手,还是一个能分析文档并生成报告的系统,你大概率会面临一个共同的起点:从零开始。这意…...

PyTorch Lightning深度学习工程化实战指南

1. 课程定位与核心价值 这个Python深度学习迷你课程的设计初衷,是帮助具备基础Python编程能力的学习者,在最短时间内掌握深度学习核心技术的工程化应用能力。不同于传统学院派教学,我们采用"问题驱动案例实战"的模式,重…...

【独家首发】MCP 2026医疗数据安全配置验证工具包(含自动化扫描脚本+等保测评报告生成器),仅限前200家三级医院申领

更多请点击: https://intelliparadigm.com 第一章:MCP 2026医疗数据安全配置标准体系概览 MCP 2026(Medical Configuration Protocol 2026)是由国际医疗信息技术联盟(IMITF)发布的全新医疗数据安全配置基准…...

OpenCV中SVM算法原理与图像分类实战

1. 支持向量机与OpenCV的深度整合支持向量机(SVM)作为机器学习领域的经典算法,在OpenCV计算机视觉库中有着成熟的实现。我在实际图像分类项目中多次采用这种组合方案,特别是在处理小样本、高维度数据时,SVM的决策边界优…...

R语言描述性统计:数据分析第一步与实战技巧

1. 为什么描述性统计是R语言数据分析的第一步每次拿到新数据集时,我做的第一件事就是运行描述性统计。这就像医生问诊时的基础检查,能快速发现数据的"体温"和"脉搏"。在R中,summary()函数是我的听诊器,30秒内…...

AI数据中心800VDC供电架构的技术突破与应用

1. AI工厂的电力革命:为什么800VDC成为下一代基础设施的核心在传统数据中心时代,电力系统设计往往被视为服务器机房的配套工程。但当我们进入生成式AI爆发的新纪元,这个认知被彻底颠覆。现代AI工厂的电力需求正在以惊人的速度增长——单个机架…...

副业焦虑的心理学分析与应对方法论

摘要副业焦虑已成为当代职场人群的普遍心理状态。本文从心理学视角分析副业焦虑的三大来源(社会比较焦虑、行动瘫痪焦虑、结果不确定性焦虑),提出"可控小确幸"理论框架,并设计一套基于自我决定论(SDT&#x…...

LangFlow:可视化低代码平台,快速构建LLM应用工作流

1. 项目概述:为什么我们需要LangFlow这样的AI应用构建工具?如果你最近在尝试将大型语言模型(LLM)集成到自己的业务或项目中,大概率会遇到一个共同的困境:想法很美好,落地很骨感。你构思了一个智…...

MatGPT:在MATLAB中无缝集成ChatGPT,打造AI增强的科学计算工作流

1. 项目概述如果你是一名MATLAB用户,同时又对ChatGPT这类大语言模型(LLM)的强大能力感到好奇,那么你很可能面临一个尴尬的局面:要么在两个工具之间反复切换,复制粘贴代码和问题;要么就得忍受在浏…...

【flowable 7.2.0 二开之三:基于 Flowable 7.2 的审批流系统解压即用】

flowable 7.2.0 二开之三:基于 Flowable 7.2 的审批流系统解压即用背景和痛点技术架构核心功能实现1. 流程设计器集成2. 表单设计器集成3. 条件分支实现4. 办理人动态分配5.字段级权限控制项目亮点开源版 vs 商业版如何获取背景和痛点 工作流引擎如 Flowable、Camu…...

MCP 2026适配不是选修课——为什么2026年Q2后所有新车型公告将自动驳回未通过MCP-TPMv2.1验证的申报?

更多请点击: https://intelliparadigm.com 第一章:MCP 2026强制适配政策的合规性底层逻辑 MCP(Model Compliance Protocol)2026 强制适配政策并非单纯的技术升级指令,而是基于可验证性、可审计性与跨域互操作性三重约…...

基于安卓平台的公交实时拥挤度查询系统

博主介绍:✌ 专注于Java,python,✌关注✌私信我✌具体的问题,我会尽力帮助你。一、研究目的本研究旨在设计并实现一种基于安卓平台的公交实时拥挤度查询系统以解决城市公共交通领域存在的信息不对称与资源分配效率低下问题。随着城市化进程加速及移动互联…...

车载MCU资源告急!MCP 2026强制要求TSN+SecOC双栈部署,4步实现RTOS内存占用压缩32%

更多请点击: https://intelliparadigm.com 第一章:MCP 2026标准核心约束与车载MCU资源瓶颈分析 MCP 2026(Microcontroller Certification Profile 2026)是ISO/SAE联合工作组新近发布的车载微控制器功能安全与实时性认证基准&…...

redis中缓存穿透,及解决方案

Redis 缓存穿透是指客户端请求查询的数据,在 Redis 缓存和后端数据库中根本都不存在,导致每次请求都会绕过缓存,直接打到数据库上。如果遭遇高并发请求或恶意攻击,数据库会因为承受不住这种无效查询的压力而崩溃。🎯 缓…...

JeecgBoot企业级低代码平台:Spring Boot+Vue3架构解析与实战指南

1. 项目概述:一个企业级低代码开发平台的深度剖析最近几年,低代码开发平台的热度居高不下,几乎成了企业数字化转型的“标配”话题。但说实话,市面上很多号称“低代码”的产品,要么是功能简单的表单工具,要么…...

DeepXDE完整安装指南:5种方法快速配置科学机器学习环境

DeepXDE完整安装指南:5种方法快速配置科学机器学习环境 【免费下载链接】deepxde A library for scientific machine learning and physics-informed learning 项目地址: https://gitcode.com/gh_mirrors/de/deepxde DeepXDE是一款功能强大的开源科学机器学习…...

Claude Code技能精选指南:从信息过载到高效AI工作流构建

1. 项目概述:一份为Claude Code深度用户量身定制的技能精选指南如果你正在使用Claude Code,并且已经厌倦了在GitHub、skills.sh、LobeHub等各个平台间来回穿梭,只为寻找一个真正能提升工作效率的Skill,那么你找对地方了。这个名为…...

STM32F103 学习笔记-21-串口通信(第4节)—串口发送和接收代码讲解(下)

本章面向STM32零基础新手,基于STM32F103标准库开发,从USART串口单字节发送的核心原理出发,逐步扩展实现16位数据、数组、字符串发送功能,并讲解C标准库printf/scanf的重定向方法。你可以把USART串口理解为STM32的“有线电话”——…...

笔记软件换了一个又一个,Tolaria让知识库真正属于你

知识管理这件事,说起来容易,做起来却总让人觉得哪里不对劲。笔记软件换了一茬又一茬,从Evernote到Notion,从Obsidian到Logseq,每换一次就要折腾一次迁移,每换一次就要重新适应一套逻辑,到头来真…...

手把手教你搞定移远EC200U/EC25的Linux驱动:从硬件检查到串口映射的保姆级教程

手把手教你搞定移远EC200U/EC25的Linux驱动:从硬件检查到串口映射的保姆级教程 刚接触移远4G模块的开发者,往往会在Linux驱动适配环节遇到各种"坑"。本文将以EC200U和EC25为例,带你完整走通从硬件检查到功能稳定的全流程。不同于零…...

基于LangChain与Azure OpenAI构建智能问答云函数实战指南

1. 项目概述:构建一个基于LangChain与Azure OpenAI的智能问答函数最近在折腾一个有意思的东西:如何把一个简单的用户提问,通过云函数快速变成一个结构化的、有上下文的智能对话。这听起来像是需要一整套复杂的后端服务,但实际上&a…...

AI环境管理框架AEnvironment:解决多模型开发部署难题

1. 项目概述与核心价值最近在折腾一个挺有意思的项目,叫inclusionAI/AEnvironment。乍一看这个名字,可能有点抽象,但如果你正在做AI应用开发,特别是涉及到多模型、多环境、复杂依赖管理的场景,这个项目很可能就是你一直…...

AI Agent Harness Engineering 盈利模式设计:订阅制、按次付费与定制化服务

AI Agent Harness Engineering 盈利模式设计:订阅制、按次付费与定制化服务 关键词 AI Agent 工具链工程、Agent Harness 订阅制分层、Token 经济下按次计费优化、定制化 Agent 基础设施 ROI、Agent 生态协作分成、可观测性驱动的价值锚定、企业级 AI 安全合规附加模块 摘要…...

Akagi麻雀助手:终极指南 - 如何用AI提升你的雀魂麻将水平

Akagi麻雀助手:终极指南 - 如何用AI提升你的雀魂麻将水平 【免费下载链接】Akagi 支持雀魂、天鳳、麻雀一番街、天月麻將,能夠使用自定義的AI模型實時分析對局並給出建議,內建Mortal AI作為示例。 Supports Majsoul, Tenhou, Riichi City, Am…...

SpringBoot+Vue垃圾分类回收管理系统源码+论文

代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹 分享万套开题报告任务书答辩PPT模板 作者完整代码目录供你选择: 《SpringBoot网站项目》1800套 《SSM网站项目》1500套 《小程序项目》1600套 《APP项目》1500套 《Python网站项目》…...

Spring Boot + 策略模式:增强接口扩展性的最佳实践

一、为什么需要策略模式?在实际业务开发中,经常会遇到一个接口有多种不同实现方式的场景。例如:支付系统:微信支付、支付宝支付、银行卡支付订单折扣:满减、打折、VIP特价文件处理:PDF导出、Excel导出、CSV…...

SpringBoot+Vue实验室开放管理系统源码+论文

代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹 分享万套开题报告任务书答辩PPT模板 作者完整代码目录供你选择: 《SpringBoot网站项目》1800套 《SSM网站项目》1500套 《小程序项目》1600套 《APP项目》1500套 《Python网站项目》…...