目录
问题描述
在JDK1.7版本下,HashMap在多线程并发下会出现死循环
原因剖析
首先在jdk1.7中,HashMap的底层是使用数组+链表实现的,而链表使用的是头插法插入数据
多线程并发时,在扩容的时候,新的数组中的某个位置链表,使用头插法插入数据的过程中,指针指向可能会出现问题,造成循环链表
JDK1.7HashMap扩容过程
源码
//扩容后将数据填充进新桶
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);//定位Hash桶,计算的结果可能为:初始位置 或者 初始位置 + 扩容量
e.next = newTable[i];//扩容插入也会采用头插法,与旧的hash桶相比链表的顺序可能会被颠倒,并且分散到 初始位置 和 初始位置 + 扩容量两个位置中
newTable[i] = e;
e = next;
}
}
}
图解
- 假设现在hashmap数组的初始长度为3,有一