HashMap多线程死锁

多线程环境下,HashMap扩容会导致死锁,下面图解过程:

并发下的Rehash(多线程)
1)假设我们有两个线程,都执行以下扩容代码。

 

do {
Entry<K,V> next = e.next; // <--假设线程一执行到这里就被调度挂起了,执行其他操作
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
} while (e != null);

 


而我们的线程二执行完成了。于是我们有下面的这个样子:

 

 

注意,因为Thread1的 e 指向了key(3),而next指向了key(7),其在线程二rehash后,指向了线程二重组后的链表。我们可以看到链表的顺序被反转后。在这里线程一变成了操作经过线程二操作后的HashMap。

2)线程一被调度回来执行。
先是执行 newTalbe[i] = e;
然后是e = next,导致了e指向了key(7),
而下一次循环的next = e.next导致了next指向了key(3)。

 

 


3)一切安好。
线程一接着工作。把key(7)摘下来,放到newTable[i]的第一个,然后把e和next往下移。这个元素所在的位置上已经存放有其他元素了,那么在同一个位子上的元素将以链表的形式存放,新加入的放在链头,而先前加入的放在链尾。

 

 

4)环形链接出现。
e.next = newTable[i] 导致 key(3).next 指向了 key(7)。
注意:此时的key(7).next 已经指向了key(3), 环形链表就这样出现了。

 

 


于是,当我们的线程一调用到,HashTable.get(11)时,悲剧就出现了——Infinite Loop

 

本文摘自  如有侵权,请联系我!!! 

 

posted @   高压锅里的大萝卜  阅读(287)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示