关于HashMap扩容造成死循环的介绍

2023-11-12

一、造成死循环的原因

HashMap扩容导致死循环的主要原因在于扩容后链表中的节点在新的hash桶使用头插法插入。新的hash桶会倒置原hash桶中的单链表,那么在多个线程同时扩容的情况下就可能导致产生一个存在闭环的单链表,从而导致死循环。
在JDK1.8中,HashMap是不会造成死循环的,因为在JDK1.8中,采用的是尾插法,保证了链表的顺序与之前一致。而且在1.8中链表过长时会转换为红黑树,在转换为红黑树前,也是先根据尾插法生成新链表再进行转换的,所以是不会造成死循环的。

二、JDK1.7中的HashMap扩容原理

在JDK1.7中,HashMap扩容时会通过transfer函数将元素添加到扩容后的数组中,并将table的索引指向这个新的数组

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;
			do {
				//保留要转移指针的下一个节点
				Entry<K, V> next = e.next;
				//计算出要转移节点在hash桶中的位置
				int i = indexFor(e.hash, newCapacity);	-----------------1
				//使用头插法将需要转移的节点插入到hash桶中原有的单链表中
				e.next = newTable[i];					-----------------2
				//将hash桶的指针指向单链表的头节点
				newTable[i] = e;						-----------------3
				//转移下一个需要转移的节点
				e = next;
			} while (e != null);
		}
	}
}

三、死链过程分析

首先假设在扩容时,hash表中有一个单链表,单链表中有两个元素:元素1和元素2

如果该HashMap为单线程操作时
执行过程:
首先 e = 元素1
执行到 next = e.next 的时候 next =元素2
从 1 到 3 的过程会将 元素1 按照头插法插入到newtable[i]所引用的单链表中
然后 e = next 会将 next 赋值给 e,所以就有 e = 元素2
判断后 e != null,继续循环,然后以同样方式插入元素2
因为 元素2 的 next 为 null 所以最后 e = null
这时候循环就结束了,原链表的顺序由 元素1—>元素2 变成了 元素2—>元素1(结果如图所示)。
正常扩容
如果该HashMap为多线程操作时(假设有T1、T2两个线程)
执行过程:
T1执行到 next = e.next;时挂起
T2开始执行并且执行完了整个流程,也就是说T2把所有元素都插入了新数组之后,原来
的table引用现在指向了 newtable,即 table = newtable;
这时T1回归继续执行,这时就会有如下场景
死循环的条件状态
当元素1正常插入后 next 是 元素2,e = next = 元素2,继续执行插入
此时,由于原表中 元素2 的 next 已经被T2所修改,不再是T1挂起时的 next = null了,所以T1就会碰到如下情况,因为 next 永远都不为空,所以就会一直循环执行插入操作,造成死循环。(图中这种状态的链表称为死链)
形成死链

四、避免死循环

第一种方式:使用HashTable
HashTable和HashMap一样都实现了Map接口,但是HashTable是一个线程安全的类,所以不会出现死循环问题。
第二种方式:使用Collections.synchronizeMap(hashMap)
该方法是Collections类中的静态方法,返回的是一个线程安全的HashMap
第三种方式:使用concurrentHashMap
concurrentHashMap也是一个线程安全类,他比HashTable更为高效。在HashTable中,使用的是同一个锁,所以当一个线程操作某一个功能时,其他线程想要操作另外的功能就要等待锁被让出来。而concurrentHashMap采用了【锁分段】技术,不同的地方使用了不同的锁,功能之间的锁不一样,操作不同功能时就不再需要等待,这样就大大提高了执行效率。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于HashMap扩容造成死循环的介绍 的相关文章

  • 机器学习--决策树(10)

    一 基本概念 1 1 是什么 分类决策树模型是一种描述对实例进行分类的树形结构 相当于if then结构 决策树由节点和有向边构成 节点有两种 一种是内部节点 表示一个特征或者属性 另一种是叶子节点 表示一个决策结果 1 2 优缺点 优点
  • Fedora的启动方式(命令行启动)

    Linux有6种不同的运行级别 默认的情况下Fedora安装完成后是从X Window启动的 X Window占用系统资源很大 所以对于我们仅仅想使用命令行模式的人来说 界面那么大 耗费资源太多有些浪费 那如何让Fedora从命令行启动而不
  • 卷麻了,00后测试用例写的比我还好,简直无地自容......

    经常看到无论是刚入职场的新人 还是工作了一段时间的老人 都会对编写测试用例感到困扰 例如 如何编写测试用例 作为一个测试新人 刚开始接触测试 对于怎么写测试用例很是头疼 无法接触需求 只能站在用户角度去做测试 但是这样情况会导致不能全方位测
  • parallel scavenge 与parnew 区别:

    Parallel Scavenge收集器是一个新生代收集器 它也是使用复制算法的收集器 又是并行的多线程收集器 看上去和ParNew都一样 那它有什么特别之处呢 Parallel Scavenge收集器的特点是它的关注点与其他收集器不同 C
  • 一款盲盒的交友软件叫什么(微信恋爱脱单交友盲盒小程序制作开发介绍)

    盲盒的交友软件一般叫做叫 盲盒脱单神器 月老交友盲盒或者是叫做一元交友等名称都是运营商自己随便起的 微信恋爱脱单交友盲盒小程序 一般情况是以H5网页的形式进行使用 做成微信小程序的形式需要相关资质 主要功能有 幻灯片 放入盒子 随机匹配 星
  • git clone指定分支拉代码、版本回退、log/reflog对比

    指定分支clone代码 1 git clone 不指定分支 默认就是master git clone http 10 1 1 11 service tmall service git 2 git clone 指定分支 git clone b
  • 【2022/2023年硕士研究生408计算机学科考试大纲原文】+【2009-2021年408统考真题+解析PDF】

    文章目录 2009 2021年408统考真题 解析 PDF版 I 考试性质 II 考查目标 III 试形式和试卷结构 一 试卷满分及考试时间 二 答题方式 三 试卷内容结构 四 试卷题型结构 IV 考查内容 数据结构 一 线性表 二 栈 队
  • CAS 5.3自定义 登录

    自定义认证校验策略 我们知道CAS为我们提供了多种认证数据源 我们可以选择JDBC File JSON等多种方式 但是如果我想在自己的认证方式中可以根据提交的信息实现不同数据源选择 这种方式就需要我们去实现自定义认证 自定义策略主要通过现实
  • 网页中插入图片的代码

    本文转载至 http www luke99 com celuechuangyi 2011 05 6912 html 如何在网页中插入图片呢 只要有图片的地址 就可以通过代码设置而放入我们的网页的 代码具体如下 img src 其中蓝色部分为
  • 牛客网题集——Min Value(逻辑)

    Min Value 牛客网测试平台 题意 一个由 N 个数组成的序列 a1 a2 a3 an 1 an 从中任选两个数 ai 和 aj 使得 ai aj 的绝对值最小 并且计算出 i j 的值 其中 i j 输入描述 输入第一行包含一个正整
  • 调用高德地图展示车辆行驶轨迹

    如何在页面中使用高德地图并分页展示多段历史轨迹 引入高德地图的JavaScript API 打开index html key 后面的内容是你自己在高德上申请 的key 引入高德组件 配置webpack 找到webpack base conf
  • 【Java日期时间】@JsonFormat与@DateTimeFormat注解的区分和使用

    目录标题 JsonFormat与 DateTimeFormat注解的区分和使用 1 背景 2 JsonFormat代码示例 步骤 注意 3 DateTimeFormat代码示例 步骤 注意 总结 JsonFormat与 DateTimeFo
  • QWizardPage、QWizard

    QWizardPage 一 描述 QWizard 代表一个向导 每个页面都是一个 QWizardPage Page 提供了五个可以重新实现以提供自定义行为的虚函数 当用户单击向导的 Next 按钮时 将调用 initializePage 来
  • 连接数据库超时设置autoReconnect=true

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 1 问题现象 com MySQL jdbc CommunicationsException The last packet successfully received fr
  • 2021-07-26

    解决 Action client not connected arm gripper controller follow joint trajectory ERROR 1627267012 953273779 3804 152000000
  • cin中输入空格断开的解决方法

    cin中输入空格断开的解决方法 cin gt gt a 此时输入 hello world cout lt
  • LaTeX添加包

    将包文件夹放入 CTEX MiKTeX tex latex目录中
  • Head First的MVC之歌(英文版)

    MVC之歌 歌名 模型 视图 控制器 ModelViewController 词曲 James Dempsey https pan baidu com s 1PXDVDqRQVpKcZ1bQwCLNLQ 请大佬 翻译并唱 出来
  • 和为 K 的最少斐波那契数字数目(贪心)

    题目描述 给你数字 k 请你返回和为 k 的斐波那契数字的最少数目 其中 每个斐波那契数字都可以被使用多次 斐波那契数字定义为 F1 1 F2 1 Fn Fn 1 Fn 2 其中 n gt 2 数据保证对于给定的 k 一定能找到可行解 示例
  • 增强网关设计与使用

    增强网关 目的 整合错误码 对外显示友好 对内便于快速定位问题 记录出错请求 依照错误码制定处理策略 设计 状态码格式 示例 E01001B002 解析 E 统一前缀 表明异常 01 应用标识 001 功能域 B 错误类型 002 错误码

随机推荐

  • vue 3.0新特性之reactive与ref

    vue 3 0新特性 参考 https www cnblogs com Highdoudou p 9993870 html https www cnblogs com ljx20180807 p 9987822 html 性能优化 观察者机
  • Allegro自动备份PCB设计文件的方法

    受到误删原理图的影响 立刻把PCB的自动备份功能设置一下 和原理图备份不一样的是PCB备份文件和源文件的格式相同 只是名称不一样 这个名称是自己设置的 步骤如下 点击 Setup gt User Preferences 弹出 User Pr
  • Linux 端 Kaggle 数据集下载:API 下载

    Linux 端 Kaggle 数据集下载 API 下载 一 准备好 kaggle json 文件 1 登录 Kaggle 官网 2 点击右上角头像 gt Your Profile gt Account gt Create New Token
  • Pandas_设置单元格条件格式1——指定值字体变色、指定值设置背景色

    转载于 https www cnblogs com wodexk p 10801344 html
  • 普通工程师和高级工程师的差别在哪里?如何快速突破?

    作者 王拥军 编辑 迷鹿 王拥军 毕业于天津大学计算机系 拥有从计算机硬件到操作系统安全 从后台服务器到客户端的全平台工作经历 目前在腾讯自选股从事互联网证券软件研发管理 对上市公司及创业团队的产品 文化 经营等具有独到的见解 个人公众号
  • linux设置系统时间

    我们一般使用 date s 命令来修改系统时间 比如将系统时间设定成20066年10月19日的命令如下 date s 10 19 2006 将系统时间设定成下午1点12分0秒的命令如下 date s 13 12 00 注意 这里说的是系统时
  • 【字节面试题】小于n的最大数

    标题 小于n的最大数 题目描述 给定一个数你 入23121 给定一个数组A如 2 4 9 求由A中元素组成的 小于n的最大数 如小于23121的最大数是22999 思路 1 把数组排序 2 把int转换成字节数组 从第一个开始变量 如2 从
  • App6种常见的数据加载设计

    设计师在进行APP设计的设计时 往往会更加专注于界面长什么样 界面和界面之间怎么跳转 给予用户什么样的操作反馈 却偏偏特别容易忽略掉一个比较重要的环节 就是APP数据加载中的设计 所以会导致我们看到的APP 往往有着华丽的启动界面 然后就是
  • Python3, 19行代码,让微信登录页面地球转起来,涨见识了。

    19行代码动态展示微信地图 1 引言 2 代码实战 2 1 思路 2 2 示例 2 2 1 经纬度 2 2 2 制作gif 3 总结 1 引言 小屌丝 鱼哥 最近在干啥嘞 小鱼 干活呗 不然能干啥 小屌丝 嘿嘿 小鱼 你这笑的 怎么 那么
  • FPGA_分频(信号使能分频与计数器分频)(奇偶分频)

    时钟对于 FPGA 是非常重要的 但板载晶振提供的时钟信号频率是固定的 不一定满 足工程需求 所以分频和倍频还是很有必要的 一 计数器分频 这里通过计数的方式来实现分频 1 通过计数器来实现6分频 两种方式 第一种直接通过计数方式直接获取获
  • 华为OD机试 Java 实现【整型数组合并】【牛客练习题】

    一 题目描述 将两个整型数组按照升序合并 并且过滤掉重复数组元素 输出时相邻两数之间没有空格 二 输入描述 输入说明 按下列顺序输入 输入第一个数组的个数 输入第一个数组的数值 输入第二个数组的个数 输入第二个数组的数值 三 输出描述 输出
  • Qt添加第三方字体

    最近开发项目时 据说不能用系统自带的微软雅黑字体 于是找一个开源的字体 思源黑体 这个是google和Adobe公司合力开发的可以免费使用 本篇记录一下Qt使用第三方字体的方式 字体从下载之家下载http www downza cn sof
  • C#文件后缀名详解

    sln 解决方案文件 为解决方案资源管理器提供显示管理文件的图形接口所需的信息 csproj 项目文件 创建应用程序所需的引用 数据连接 文件夹和文件的信息 aspx Web 窗体页由两部分组成 视觉元素 HTML 服务器控件和静态文本 和
  • 什么是P = NP?问题

    文章目录 引言 天才基本法 什么是P NP问题 P NP 成立吗 总结 提示 以下是本篇文章正文内容 Java系列学习将会持续更新 引言 今天我们先放松一下 这篇文章并不是Java课程的学习 而是带大家认识一个学术问题 但是请大家放心 这里
  • libevent多线程使用事项

    在linux平台上使用c开发网络程序的同志们一般情况下都对鼎鼎大名的libevent非常的熟悉了 但是一些新进入此领域的new new people们对此都是一头雾水 原本的迷茫再加上开源软件一贯的 帮助文件 缺失作风 让我们这些新手们显的
  • 免费C/C++编译器

    不好意思 等到现在才想到要写这篇文章 怎么说呢 情况是这样的 刚开始我学习C语言时 是想在机器上安装visual c 的 因为Turbo C太古老了 用起来不方便 所以很自然地想安装vc 不过不知道大家有没有发现vc很大 而且有些机子就是安
  • 线程是什么意思

    线程是操作系统能够进行运算调度的最小单位 它被包含在进程之中 是进程中的实际运作单位 一条线程指的是进程中一个单一顺序的控制流 一个进程中可以并发多个线程 每条线程并行执行不同的任务 在Unix System V及SunOS中也被称为轻量进
  • Structural Time Series modeling in TensorFlow Probability

    在邯郸学步后 想要深入用好Tensorflow中的STS model 还是要静下心来 好好阅读点材料 f t f 1
  • 分页插件pagehelper配置和 使用;

    先看结论 在看代码是实现 代码就这么多 现在来看配置 配置 1 pom xml加入这个依赖 com github pagehelper pagehelper 3 7 5 com github jsqlparser jsqlparser 0
  • 关于HashMap扩容造成死循环的介绍

    一 造成死循环的原因 HashMap扩容导致死循环的主要原因在于扩容后链表中的节点在新的hash桶使用头插法插入 新的hash桶会倒置原hash桶中的单链表 那么在多个线程同时扩容的情况下就可能导致产生一个存在闭环的单链表 从而导致死循环