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

jdk1.7 在多线程下扩容可能导致的死循环问题

首先先看看 hashmap 在jdk1.7 下扩容的核心方法

void transfer(Entry[] newTable) { Entry[] src = table; int newCapacity = newTable.length; // 遍历旧数组的每一个格子(桶) for (int j = 0; j < src.length; j++) { Entry<K,V> e = src[j]; if (e != null) { src[j] = null; // 断开旧数组的引用,虽然不是必须的,但有助于GC // 遍历链表,把链表上的节点一个一个摘下来,重新放到新数组里 do { // 【关键点1】先保存下一个节点,防止待会链表断了找不到后面的人 Entry<K,V> next = e.next; // 计算这个节点在新数组中的下标 int i = indexFor(e.hash, newCapacity); // 【关键点2】头插法核心:将当前节点 e 的 next 指向新数组位置原本的头节点 e.next = newTable[i]; // 【关键点3】将新数组该位置的头指针指向 e(e 变成了新的头节点) newTable[i] = e; // 【关键点4】继续处理旧链表的下一个节点 e = next; } while (e != null); } } }

可以看到,jdk1.7 版本下的扩容依靠的是头插法实现元素搬移

头插法 的特点:假设旧数组某个位置的链表是A -> B -> C。 因为代码逻辑是:每次把新来的元素插到最前面(e.next = newTable[i]然后newTable[i] = e)。 所以搬运到新数组后,顺序会倒置,变成C -> B -> A

为什么JDK 1.7用头插法? 设计者当时认为,后插入的数据被访问的概率更高(热点数据),放在头部查得快。但这在多线程下埋下了祸根。

那其实在多线程的情况下就会有问题了,举个例子:

假设有两个线程Thread 1Thread 2同时在扩容。 旧链表结构:A -> B。 线程 1 执行到你注释的那一行挂起了(Paused):

Entry<K,V> next = e.next; // 线程1在这里卡住了! // 此时对于线程1来说: e = A, next = B
接下来可能发生的事情:
  1. 线程 2 抢占 CPU 完成了扩容
    • Thread 2 把AB都搬到了新数组。
    • 注意:因为是头插法,顺序反了
    • 在新内存里,现在的链表结构是:B -> A(B 指向 A,A 指向 null)。
  1. 线程 1 醒来继续执行
    • Thread 1 里的变量还停留在挂起前的状态:e = Anext = B
    • Thread 1 开始干活:
      • 将 A 指向 B
      • 头节点变成 A
      • 此时 A 指向 B,B 指向 A(死循环开始)
  1. 线程 1 接着处理 B,B 头插当头节点,此时 B 指向 A,A 指向 B
  2. 然后接着处理 A,A 头插当头节点,此时 A 指向 B,B 指向 A
  3. 然后循环往复 A,B 轮流当头节点,死循环

如图:


http://www.jsqmd.com/news/104803/

相关文章:

  • 2025年热门的发电机组实力厂家TOP推荐榜 - 行业平台推荐
  • 2025年比较好的85英寸触摸一体机厂家最新TOP排行榜 - 行业平台推荐
  • AI绘画控制技术深度解析:ControlNet如何实现精准构图控制
  • Obsidian文档结构优化利器:智能标题自动编号完全指南
  • 带你读懂原码反码补码
  • 基于Java的司机服务智慧管理系统的设计与实现全方位解析:附毕设论文+源代码
  • 3大诊断策略:智能风扇调速系统的精准调校指南
  • 2025年口碑好的非标钛棒厂家推荐及选择指南 - 行业平台推荐
  • 水飞蓟哪个牌子最好最安全,水飞蓟哪个品牌好排名前十,水飞蓟养肝哪家强? - 博客万
  • EmotiVoice情感过渡平滑性测试:避免情绪跳跃突兀
  • 12.17
  • Redash数据可视化终极指南:从零开始构建专业仪表板
  • Book118文档下载终极指南:Java工具快速获取可预览文档
  • 2025年口碑好的面粉机械热门厂家推荐榜单 - 行业平台推荐
  • 计算机毕业设计springboot民宿信息展示与管理及可视化平台系统 基于SpringBoot的民宿数据可视化与智能运营平台 融合大数据的民宿资源聚合及多维分析系统
  • WPF给类添加属性通知 INotifyPropertyChanged
  • SRv6技术完全指南(1):下一代网络的核心引擎
  • 百度网盘秒传链接高效使用指南:从零基础到精通
  • 汇川 PLC 从入门到 EtherCAT 运动控制,全套资料齐了
  • 2025年比较好的护墙灯衣柜灯/线型灯衣柜灯厂家推荐及采购参考 - 行业平台推荐
  • Windows任务栏革命:用Taskbar Groups打造极致高效工作环境
  • 企业级数据导入导出框架AGEIPort:架构解析与深度实践
  • 2025值得推荐的低温等离子清洗机供应商TOP5:深度测评指 - mypinpai
  • 【赵渝强老师】Redis消息的生产者消费者模式
  • 融合语音识别与语言理解的技术探索
  • 2025年热门的防静电opp束带/透明opp束带最新TOP品牌厂家排行 - 行业平台推荐
  • 网络加速革命:用TurboACC彻底解决OpenWrt路由器性能瓶颈
  • AMD 780M APU终极优化指南:30%性能提升的完整配置方案
  • 边缘存储终极方案:云边数据同步实战深度解析
  • 18、Kubernetes 滚动更新、可扩展性与配额管理