HashMap中扩容导致环链现象分析

本文深入探讨HashMap在扩容过程中可能出现的环链现象,分析了多线程环境下,由于头插法导致的环链形成原因,并指出Java 1.8通过改用尾插法避免了这个问题,但并发安全仍需注意。
摘要由CSDN通过智能技术生成

目录

为什么会出现环链?

什么时候会出现环链?

出现环链的场景:

      数据准备、结果预期

      模拟的转移代码

  多线程的场景分析

 形成的根本原因

数据分析

线程一数据变化

第一次循环

 第二次循环

线程二开始执行


为什么会出现环链?

       HashMap是线程不安全的,并且其扩容的代码会将原来的链表进行反序,例如原先的是 3-> 2-> 1,现在还在同一位置则是 1->2->3,那么在多线程并发操作的情况下一个正序,一个反序,就会有可能出现。

什么时候会出现环链?

      多线程操作,同时去扩容,当一个线程已经操作完毕了,将原来的顺序反过来了;另一个线程再开始执行扩容代码,此时就会出现环链。

 正常的扩容转移效果如下:

代码运行的结果如下: 

3 ->2 ->3


出现环链的场景:

      数据准备、结果预期

       首先初始化一个数组,数组的一个元素是一个链表,有三个对象,模拟扩容的操作,将其中的一个分散到新数组的一个槽位中,将剩余的两个仍形成一个链表的结构。 

      模拟的转移代码

        散列的函数粗糙点,主要是为了达到两个元素存在于一个槽位的目的

public static void transfer(Entry[] newTable, Entry[] table) {
		for (Entry e : table) {
			while (e != null) {
				//1 、拿出下一个以及后面的所有
				Entry next = e.next;
				// 散列效果看i的分布
				int i = Integer.parseInt(e.key) > 1 ? 1 : 0;
				// 2、断开e与之前的,指向新的;新的可能是空,也可能有对象 ,有对象的话就是头插法
				e.next = newTable[i];
				// 3、再把E新操作后的一串对象赋值给新的数组。 2/3这两步实现头插转移
				newTable[i] = e;
				//4、指针移动到下一个,直到结束
				e =
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值