JDK1.7中HashMap存在并发成环的问题。问题发生在扩容搬运的时候,具体代码如下。
void transfer(Entry[] newTable, boolean rehash) {
int newCapacity = newTable.length;
//table是旧table,也就是扩容前的table
for (Entry<K,V> e : table) {
//e为槽位的头节点,通过头节点遍历槽位
while(null != e) {
Entry<K,V> next = e.next;
if (rehash) {
e.hash = null == e.key ? 0 : hash(e.key);
}
//获得e在新table中位置
int i = indexFor(e.hash, newCapacity);
//采用头插法
//将e的next设置为newTable[i],也就是i对应的头节点
//然后将e设置为newTable[i],也就是i对应的头节点
//是一种头插做法
e.next = newTable[i];
newTable[i] = e;
e = next;
}
}
}
如上图所示,如果线程1完成了槽位1的搬运,也就是将旧table[1]中的节点搬运到了新table[1]中。对应的排列为 b,a,null,此时b为新table[1]的头节点为b。
这时来了一个线程2也来搬运槽位1,这时,旧table中的头节点为a,按照头插法,会将a.next = newTable[i],这时线程1已经将新table[1]的头节点为a,也就是a.next = b。之前线程1在搬运的时候已经设置b.next = a。
这就出现了环,会导致map遍历或者插入一直死循环,导致CPU飙升!