5张图讲明白JDK1.7下的HashMap死循环(原理+实战)

目录

image

情景再现

网络上很多文章说HashMap死循环都是理论分析,其一是没有自己实验过,甚至给出的实验程序都是错误的,不能再现死循环的BUG,其二是给出的示意图不够详细,很多细节忽略了让人难以理解,本文在前人总结的基础上摸索出了实现死循环的方法,记录成文。

死循环原因

我们首先思考一下在什么样的情况下HashMap会死循环,死循环的原因不外乎是在多线程的同时扩容,在JDK 1.7的HashMap中,当hash冲突时,采用头插法拉链表,所谓头插法,即在每次都在链表头部(即桶中)插入最后添加的数据

当触发扩容阈值准备扩容的时候,会循环旧桶中的每个元素,重新计算hash值然后再次分配到新的桶中,这个过程如果产生hash冲突,那也会采用头插法拉链表,循环的时候是从头到尾,而头插法插入的时候,尾巴上的元素反而会变成头元素,相当于逆序了

当一个线程A在扩容还未完成的时候,不巧的是失去了CPU时间片,不能获得执行机会,另外一个线程B抢先扩容完毕了,并且链表变成了逆序,而线程A还在按照顺序操作,造成指针混乱,于是出现死循环,当然这么说过于笼统也说不清楚,后文讲解原理的时候会详细到每个步骤!

实验环境

IDEA + JDK 1.7,自从Oracle改版以后需要登录才能下载,而且链接不是很好找,这里推荐一个下载站点:
http://java.sousou88.com/spec/oraclejdk.html

实验思路

既然要多线程才会实现,那么可以利用IDEA的多线程DEBUG操作将两个线程同时停在扩容操作处,然后让其中一个线程先扩容完,另外一个线程再次扩容造成死循环

程序代码


import java.io.IOException;
import java.util.HashMap;

/**
 * 测试在JDK 1.7中 HashMap出现死循环
 */
public class Main {

    /**
     * 这个map 桶的长度为2,当元素个数达到  2 * 1.5 = 3 的时候才会触发扩容
     */
    private static HashMap<Integer,String> map = new HashMap<Integer,Strin
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码狂魔v

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值