hashmap并发情况下的成环原因

发布于:2021-07-29 12:09:19

hashmap是一个非线程安全的集合。


他的线程不安全出现在,并发情况下可能会出现链表成环的问题,导致程序在执行get操作时形成死循环。


hashmap成环原因的代码出现在transfer代码中,也就是扩容之后的数据迁移部分,代码如下:


void transfer(Entry[] newTable, boolean rehash) {
int newCapacity = newTable.length;
for (Entry e : table) {
while(null != e) {
Entry next = e.next;
if (rehash) {
e.hash = null == e.key ? 0 : hash(e.key);
}
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
}
}
}

解释一下transfer的过程:


首先获取新表的长度,之后遍历新表的每一个entry,然后每个ertry中的链表,以反转的形式,形成rehash之后的链表。


并发问题:


若当前线程此时获得ertry节点,但是被线程中断无法继续执行,此时线程二进入transfer函数,并把函数顺利执行,此时新表中的某个位置有了节点,之后线程一获得执行权继续执行,因为并发transfer,所以两者都是扩容的同一个链表,当线程一执行到e.next = new table[i] 的时候,由于线程二之前数据迁移的原因导致此时new table[i] 上就有ertry存在,所以线程一执行的时候,会将next节点,设置为自己,导致自己互相使用next引用对方,因此产生链表,导致死循环。


解决问题:


使用synchronize ,或者使用collection.synchronizeXXX方法。或者使用concurrentHashmap来解决。

相关推荐

最新更新

猜你喜欢