4.5.1HashMap死循环分析

注:源图和总结来自享学课堂,自己消化之后略有补充修改

备注:基于1.7jdk进行分析

备注2:强烈建议自己跟着步骤一个图一个图手动画,理解深刻一点也快一点

简介

在多线程之下,在put操作的时候,会导致HashMap的Entry链表死循环,导致CPU利用率接近100%

单线程下HashMap的扩容

原理

扩容只要有三个方法:

AddEntry

resize

transfer

扩容总结

1、扩容2倍

2、新建数组,容量是以前的2倍

3、轮询oldtable上的值,计算在newtable中的位置,采用头插法以链表形式连接

实例

有如下的hashMap

按照代码中的方法,移动如下

第一次:

第二次:

第三次:

并发下的扩容

初始值:

线程1刚执行完Entry<K,V> next = e.next;就被阻塞了,线程2已经完成了所有的扩扩容操作,刚执行完Entry<K,V> next = e.next;,只剩下e.next = newTable[3] ; newTable[3] = e;  e=next

此时线程的状态是这个样子

接下来线程1开始执行newTable[i]=e,即newTable[3]=e

执行e=next

开始新一轮循环

最开始线程2不是还有最后一点没有执行完吗e.next = newTable[3] ; newTable[3] = e;  e=next,这个时候线程2完全执行完成

此时执行Entry<key,value> next = e.next;

执行e.next= newTable[3];,newTable[3] =e;

执行e=next;于是e=key(3);

开始新一轮while循环

执行e.next = newTable[i],newTable[i]=e;后,循环链表产生

产生循环链表之后,一旦线程调用get查找一个不存在的元素是(例如11,15),就会进入死循环,CPU消耗100%

总结:

HashMap的死循环是在并发扩容下发生的,因为一个线程先进行了扩容变成了倒序链表,后一个线程再扩容是,又进行了自己的散列,再次将倒序链表变成了正序链表,于是形成了一个环形,当get表中不存在的元素是,造成死循环

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章