首页 > 其他分享 >为什么HashMap会产生死循环?

为什么HashMap会产生死循环?

时间:2023-06-13 10:56:48浏览次数:66  
标签:为什么 HashMap T2 T1 线程 节点 死循环

 

HashMap 死循环是一个比较常见、比较经典的问题,在日常的面试中出现的频率比较高,所以接下来咱们通过图解的方式,带大家彻底理解死循环的原因。

前置知识

死循环问题发生在 JDK 1.7 版本中,造成这个问题主要是由于 HashMap 自身的运行机制,加上并发操作,从而导致了死循环。 在 JDK 1.7 中 HashMap 的底层数据实现是数组 + 链表的方式,如下图所示:

 

而 HashMap 在数据添加时使用的是头插入,如下图所示: 

 

HashMap 正常情况下的扩容实现如下图所示:

 

旧 HashMap 的节点会依次转移到新 HashMap 中,旧 HashMap 转移的顺序是 A、B、C,而新 HashMap 使用的是头插法,所以最终在新 HashMap 中的顺序是 C、B、A,也就是上图展示的那样。有了这些前置知识之后,咱们来看死循环是如何诞生的?

死循环执行步骤1

死循环是因为并发 HashMap 扩容导致的,并发扩容的第一步,线程 T1 和线程 T2 要对 HashMap 进行扩容操作,此时 T1 和 T2 指向的是链表的头结点元素 A,而 T1 和 T2 的下一个节点,也就是 T1.next 和 T2.next 指向的是 B 节点,如下图所示:

 

死循环执行步骤2

死循环的第二步操作是,线程 T2 时间片用完进入休眠状态,而线程 T1 开始执行扩容操作,一直到线程 T1 扩容完成后,线程 T2 才被唤醒,扩容之后的场景如下图所示:

 

 从上图可知线程 T1 执行之后,因为是头插法,所以 HashMap 的顺序已经发生了改变,但线程 T2 对于发生的一切是不可知的,所以它的指向元素依然没变,如上图展示的那样,T2 指向的是 A 元素,T2.next 指向的节点是 B 元素。

死循环执行步骤3

当线程 T1 执行完,而线程 T2 恢复执行时,死循环就建立了,如下图所示: 

 

因为 T1 执行完扩容之后 B 节点的下一个节点是 A,而 T2 线程指向的首节点是 A,第二个节点是 B,这个顺序刚好和 T1 扩完容完之后的节点顺序是相反的。T1 执行完之后的顺序是 B 到 A,而 T2 的顺序是 A 到 B,这样 A 节点和 B 节点就形成死循环了,这就是 HashMap 死循环导致的原因。

解决方案

HashMap 死循环的常用解决方案有以下 3 个:

  • 使用线程安全容器 ConcurrentHashMap 替代(推荐使用此方案)。
  • 使用线程安全容器 Hashtable 替代(性能低,不建议使用)。
  • 使用 synchronized 或 Lock 加锁 HashMap 之后,再进行操作,相当于多线程排队执行(比较麻烦,也不建议使用)。

总结

HashMap 死循环发生在 JDK 1.7 版本中,形成死循环的原因是 HashMap 在 JDK 1.7 使用的是头插法,头插法 + 链表 + 多线程并发 + HashMap 扩容,这几个点加在一起就形成了 HashMap 的死循环,解决死锁可以采用线程安全容器 ConcurrentHashMap 替代。 ​

标签:为什么,HashMap,T2,T1,线程,节点,死循环
From: https://www.cnblogs.com/shamo89/p/17476887.html

相关文章

  • clickhouse 为什么快?
    文章目录@[TOC](文章目录)前言一、什么是列式数据库?为什么要用列式数据库,优点是什么?二、clickhouse入门1.个人猜想2.使用clickhouse引入依赖yml配置扫描mapper2.生成相应代码,执行测试用例查询结果总结前言例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启......
  • 为什么很多人自学Python都放弃了?
     有些人学Python并不是因为对编程有浓厚的兴趣,或者没有经验尝试认为入门容易。因此,当他们开始学习Python时,可能会遇到一些困难或感到挫败,导致他们放弃。总的来说,python并不是你想想的那样简单。以下是可能导致放弃的原因:缺乏计算机科学和编程基础:学习Python需要具备一定的计......
  • 为什么很多人自学Python都放弃了?
    有些人学Python并不是因为对编程有浓厚的兴趣,或者没有经验尝试认为入门容易。因此,当他们开始学习Python时,可能会遇到一些困难或感到挫败,导致他们放弃。总的来说,python并不是你想想的那样简单。以下是可能导致放弃的原因:缺乏计算机科学和编程基础:学习Python需要具备一定的计算机科......
  • 为什么需要堡垒机
    什么是堡垒机堡垒机,即在一个特定的网络环境下,为了保障网络和数据不受来自外部和内部用户的入侵和破坏,而运用各种技术手段监控和记录运维人员对网络内的服务器、网络设备、安全设备、数据库等设备的操作行为,以便集中报警、及时处理及审计定责。用一句话来说,堡垒机就是用来后控制哪些......
  • 2023年6月11日,TreeSet,Comparable,HashMap
    1.Set1.TreeSetTreeSet1、存储Integer的元素,升序排列2、存储String的元素,字典排列TreeSet根据元素的不同类型使用不同的排序规则publicclasstest01{/***知识点:TreeSet*1、存储Integer的元素,升序排列*2、存储String的元素,字典排列*......
  • 男人为什么总想搞自己的初恋-带走了我一整个青春的女孩
    初恋,就是人生中爱情里面的第一个喜欢的人,那些曾经刻骨铭心地相爱、相知、难以忘怀地结束、回想起来还心存不甘的那段爱恋里的男女主角。对于大多数男人来说,体会到初恋的滋润,初恋都是在比较年轻的年龄,愿意为一个女孩子做很多事情,心甘情愿的。大多数男孩子幼稚、干净、满腔热情追求......
  • 美SEC主席公开演讲:我们为什么起诉币安和Coinbase?
       在SEC闪击币圈后,美SEC主席GaryGensler在PiperSandler全球交易所和金融科技大会发表演讲,他再次强调了监管的重要性,并指出监管已经明确,发行人、经纪交易商和交易所应该遵守。这不是指导方针不充分的问题,只是他们不想按照被监管机构告知的去做。   Gensler认为,美国资本市场......
  • 思考-为什么不想做事还特别累
    问题描述每天起来特别的累,以至于做事情的动力和欲望降到很多,直到最后不想做任何事情,这是为什么?原因分析1.心力、脑力、体力的耗尽,不是不想,而是特别累的不想做事2.想各种其他的东西,耗费所剩无几的脑力3.不知道做哪一件事情,产生矛盾的内耗......
  • 定积分上下限为什么有时候需要变有时候不需要不变?
    简单的说就是:能在式子中看到原来的积分变量就不需要重新计算积分上下限,否则就需要重新确定积分上下限,这里还有一个具体的例子和更加详细的说明可以帮助我们理解这个问题:定积分运算时的积分上下限:什么时候变?什么时候不变?——荒原之梦考研数学......
  • 冷知识: 为什么那么多名人幼年丧父?
    冷知识:为什么那么多名人幼年丧父?粉嫩表情包 2022-04-0810:00收录于合集#冷知识1000个原因1:父亲英年早逝。 原因2:不是当爹的身子不够硬朗,而是孩子来得太晚……(请看下表吧)  阮籍,出生时父亲46岁,3岁丧父。 武则天,出生时父亲47岁,12岁丧父。父母年龄差2岁,非原配。......