多线程 HashMap 死循环 问题解析
源码
resize
void resize(int newCapacity)
{
Entry[] oldTable = table;
int oldCapacity = oldTable.length;
......
//创建一个新的Hash Table
Entry[] newTable = new Entry[newCapacity];
//将Old Hash Table上的数据迁移到New Hash Table上
transfer(newTable);
table = newTable;
threshold = (int)(newCapacity * loadFactor);
}
复制代码
迁移
void transfer(Entry[] newTable)
{
Entry[] src = table;
int newCapacity = newTable.length;
//下面这段代码的意思是:
// 从OldTable里摘一个元素出来,然后放到NewTable中
for (int j = 0; j < src.length; j++) {
Entry<K,V> e = src[j];
if (e != null) {
src[j] = null;
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);
}
}
}
复制代码
我们可以知道newTable 是新创建的 是线程私有的, 因为 线程1 获取 e 和next 之后 线程2 插入执行了,执行完是 倒序的链条, 线程1 再插入 e 和next的 方向 与 线程2执行之后的 方向不对应 导致 循环两次之后 出现问题,会丢数据 ,问题主要集中在最后一次(第3此)执行之后 e,next 均指向null 循环结束
丢数据的问题比较大,
两个线程 ,
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);
复制代码
原来:3 -> 7 -> 6 -> 5( 数据5 resize的时候 分到了其他数组 这里不管它 )
线程1 在 上图位置 卡住, e1 指向3 和 next1 指向 7
线程2 执行
执行后结果为 6 -> 7 -> 3 -> null
ps:没什么画图工具 手画了一下
参考文章:http://blog.csdn.net/xiaohui127/article/details/11928865