avatar

目录
多线程 HashMap 死循环 问题解析

多线程 HashMap 死循环 问题解析

源码

resize

Code
1
2
3
4
5
6
7
8
9
10
11
12
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);
}

迁移

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void transfer(Entry[] newTable)  
{
Entry[] src = table;
int newCapacity = newTable.length;
//下面这段代码的意思是:
// 从OldTable里摘一个元素出来,然后放到NewTable中
for (int j = 0; j < src.length; j++) {
Entry e = src[j];
if (e != null) {
src[j] = null;
do {
Entry 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 循环结束

丢数据的问题比较大,

两个线程 ,

Code
1
2
3
4
5
6
7
do {  
Entry 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

文章作者: 美式不加糖
文章链接: http://yoursite.com/2018/10/14/HashMap%E5%A4%9A%E7%BA%BF%E7%A8%8B%E9%97%AE%E9%A2%98%E8%A7%A3%E6%9E%90/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 湖畔小屋
打赏
  • 微信
    微信
  • 支付寶
    支付寶