HashMap为什么会死循环?

简介: 本文分析了在Java中HashMap导致死循环的原因,主要由于在JDK 1.7及之前版本中,多线程环境下进行扩容操作时,头插法导致的链表反转,以及线程调度问题,从而形成循环链表。

典型回答

HashMap 死循环发生在JDK 1.7 之前 (包含JDK 1.7),发生死循环需要满足以下三个条件:

  1. 多线程同时执行添加操作
  2. 触发 HashMap 扩容机制
  3. JDK 1.7 之前(包含 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 和 T2next 指向的是B 节点,如下图所示:

死循环执行步骤2

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

死循环执行步骤3

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

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

目录
相关文章
|
存储 Java 索引
HashMap的执行原理
HashMap的执行原理
57 0
|
11月前
|
算法 安全 Java
hashmap死循环原因总结
hashmap死循环原因总结
43 0
|
存储 安全 容器
为什么HashMap会产生死循环?
HashMap死循环是一个比较常见、也是比较经典的面试题,在大厂的面试中也经常被问到。HashMap的死循环问题只在JDK1.7版本中会出现,主要是HashMap自身的工作机制,再加上并发操作,从而导致出现死循环。JDK1.8以后,官方彻底解决了这个问题。
92 0
|
存储 安全 Java
聊聊hashmap在1.7情况下的多线程死循环问题
在Java 1.7版本中,HashMap的扩容过程存在一个多线程环境下的死循环问题。这个问题的具体原因是由于HashMap在进行扩容时,多个线程同时进行put操作,可能会导致链表形成环形结构,从而导致get操作陷入死循环。
162 0
|
算法 安全 Java
推荐:并发情况下:Java HashMap 形成死循环的原因
推荐:并发情况下:Java HashMap 形成死循环的原因
174 1
|
算法 Java
20. 你知道为什么HashMap是线程不安全的吗?上
20. 你知道为什么HashMap是线程不安全的吗?上
72 0
20. 你知道为什么HashMap是线程不安全的吗?上
|
算法 Java
都说 HashMap 是线程不安全的,到底体现在哪儿?
都说 HashMap 是线程不安全的,到底体现在哪儿?
111 0
都说 HashMap 是线程不安全的,到底体现在哪儿?
20. 你知道为什么HashMap是线程不安全的吗?下
20. 你知道为什么HashMap是线程不安全的吗?下
99 0
|
监控 Java 网络安全
为什么JDK8中HashMap依然会死循环
为什么JDK8中HashMap依然会死循环
为什么JDK8中HashMap依然会死循环
|
算法 安全 Java
Java并发编程 - HashMap 死循环
Java并发编程 - HashMap 死循环
165 0
Java并发编程 - HashMap 死循环