为什么HashMap会产生死循环? | 您所在的位置:网站首页 › javamap扩容 › 为什么HashMap会产生死循环? |
文章合集:gitee.com/mydb/interv… HashMap 死循环是一个比较常见、比较经典的问题,在日常的面试中出现的频率比较高,所以接下来咱们通过图解的方式,带大家彻底理解死循环的原因。 前置知识死循环问题发生在 JDK 1.7 版本中,造成这个问题主要是由于 HashMap 自身的运行机制,加上并发操作,从而导致了死循环。
在 JDK 1.7 中 HashMap 的底层数据实现是数组 + 链表的方式,如下图所示:
死循环是因为并发 HashMap 扩容导致的,并发扩容的第一步,线程 T1 和线程 T2 要对 HashMap 进行扩容操作,此时 T1 和 T2 指向的是链表的头结点元素 A,而 T1 和 T2 的下一个节点,也就是 T1.next 和 T2.next 指向的是 B 节点,如下图所示:
死循环的第二步操作是,线程 T2 时间片用完进入休眠状态,而线程 T1 开始执行扩容操作,一直到线程 T1 扩容完成后,线程 T2 才被唤醒,扩容之后的场景如下图所示:
当线程 T1 执行完,而线程 T2 恢复执行时,死循环就建立了,如下图所示:
HashMap 死循环的常用解决方案有以下 3 个: 使用线程安全容器 ConcurrentHashMap 替代(推荐使用此方案)。 使用线程安全容器 Hashtable 替代(性能低,不建议使用)。 使用 synchronized 或 Lock 加锁 HashMap 之后,再进行操作,相当于多线程排队执行(比较麻烦,也不建议使用)。 总结HashMap 死循环发生在 JDK 1.7 版本中,形成死循环的原因是 HashMap 在 JDK 1.7 使用的是头插法,头插法 + 链表 + 多线程并发 + HashMap 扩容,这几个点加在一起就形成了 HashMap 的死循环,解决死锁可以采用线程安全容器 ConcurrentHashMap 替代。 是非审之于己,毁誉听之于人,得失安之于数。 公众号:Java中文社群 |
CopyRight 2018-2019 实验室设备网 版权所有 |