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 @ 2022-02-28 16:46  高压锅里的大萝卜  阅读(280)  评论(0编辑  收藏  举报