问题的描述
非普通头插导致扩容,而是扩容时,扩容的逻辑会导致节点互相引用,导致死循环
源码分析
// 扩容代码
void transfer(Entry[] newTable, boolean rehash) {
int newCapacity = newTable.length;
for (Entry<K,V> e : table) {
while(null != e) {
Entry<K,V> 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;
}
}
}
造成环状链表的就是这段扩容的代码
我们根据代码模拟一遍扩容的过程:
此时假设两个线程,同时参与扩容的过程,且线程A拿到值(e.next = nodeA)后被挂起,线程B先执行完上述代码,如图所示:
回到线程A中
线程A继续执行代码,此时newTable的Entry3已经发生了变化,那么nodeA同时也插入到Entry3中,此时nodeA指向nodeB,nodeB指向nodeA,此时线程A将进入死循环。
再贴一下代码
// 扩容代码
void transfer(Entry[] newTable, boolean rehash) {
int newCapacity = newTable.length;
for (Entry<K,V> e : table) {
while(null != e) {
Entry<K,V> 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;
}
}
}