标签:扩容 HashMap Thread JDK1.7 next 链表 死循环
咦,HashMap还会死循环么,一脸懵。在JDK1.8之前,HashMap是有可能出现死循环的,什么情况下会出现死循环呢?在put操作触发并发扩容的情况下可能会出现死循环,上源码
1.put()方法
2.进入addEntry()方法
3.进入resize()方法
4.进入transfer()方法,出现死循环的原因就在其中
假设有一个HashMap如下:
现在有Thread-A和线程Thread-B对其进行扩容,Thread-A运行到transfer()方法中的Entry<k,v> next = e.next;的时候Thread-A被挂起,Thread-B进行扩容,进行第一轮循环如下:
进入下一轮循环
Thread-B完成了扩容,就在这个时候Thread-A被唤醒,而在Thread-A中是在Entry<k,v> next = e.next;的时候被挂起的,也就是那个时候,e是key3,next=e.next是key7,于是如下图:
进行下一轮循环如下:
此刻key7的next指向key3,进行下一轮循环如下:
可以看到形成了一个循环链表,当你去get一个 key11、key15不存在的时候,就会形成死循环。
总结:HashMap之所以在并发扩容下形成死循环,是因为多个线程并发扩容时,一个线程先完成了扩容,将原本HashMap的链表重新散列到自己的表中,并且链表成了倒序,后一个线程扩容时,再一次散列搭到自己的表中,再次将倒序链表变成正序链表,于是形成了一个循环链表,当get落在这个桶上不存在的元素时,造成死循环。
标签:扩容,HashMap,Thread,JDK1.7,next,链表,死循环 来源: https://www.cnblogs.com/tanyf/p/15068408.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。