【JDK7-HashMap-扩容机制形成的链表环过程详解】

JDK7-HashMap-扩容bug

HashMap不是线程安全的key-value结构,在多线程环境下有可能存在多线程并发扩容,就有可能产生链表环,导致两个问题发生

  1. get数据时产生死循环
  2. 数据丢失问题

下面对产生链表环的问题就行分析,经典面试题。

单线程环境下扩容机制

单线程环境不会产生并发扩容,也就不会产生上述两个问题,先分析下正常场景下时如果扩容的将会为分析上述问题的分析做铺垫。

  1. 扩容代码
while(null != e) { 
	Entry<K,V> next = e.next;//第一行,线程1执行到此被调度挂起
 	int i = indexFor(e.hash, newCapacity);//第二行 
 	e.next = newTable[i];//第三行 
 	newTable[i] = e;//第四行 
 	e = next;//第五行 
}
扩容的代码说白了,就是将链表中的元素的引用指针的移动
  1. 扩容过程

在这里插入图片描述
假设由容量2扩容到4,假设扩容数组索引=key%4,扩容结束新数组结构如下
在这里插入图片描述

并发场景多线程扩容机制问题分析

假设有两个线程同时扩容
在这里插入图片描述
此时由于并发,执行完第一行代码,cpu分配给线程1的时间片到了,线程1睡眠
在这里插入图片描述
此时线程1被唤醒,从第二行代码执行
在这里插入图片描述
e和next指针变化
在这里插入图片描述
使用最新的next、e继续执行,新增了线程1扩容数组第一个节点对7的引用
在这里插入图片描述
更新next、e
在这里插入图片描述
继续执行迁移
在这里插入图片描述
红线部分就出现了链表环,当使用get方法时,正好命中在扩容数组的3号位置,遍历链表查询数据时走到链表环时无限循环,那么问题一就出现了。

另外由于元素3的next为null,导致5还未进行迁移,整个扩容工作就结束了,最终导致元素5丢失。

总结

在并发场景下的jdk7 hashMap存在风险,但是在jdk8中解决了扩容问题,解决方案的分析请看下一篇文章。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值