hashmap死锁的产生

都说hashmap是线程不安全的,多线程时候容易造成死锁

死锁的原因就在扩容的时候

原hashmap结构图假如如下,A、B是hashmap其中两个Entry,在扩容之前具有相同的index,形成链表结构,如图

 

1、线程一运行到Entry A, B = A.next,运行完这行后。线程一进入线程等待(此时链表关系A.next = B)

2、线程二正常运行,顺利完成扩容,在偶尔情况下恰好扩容之后A、B,在newTable中还是拥有相同的index,但此时由于经过了一次扩容,由于扩容过程也是头插法,所以原来在链表后的Entry变更到链表前边,链表翻转过来了。在newTable中为B.next=A,线程二结束。扩容完成,hashmap结构如下图(A,B的index都为4)

3、此时线程一唤醒,线程一还是A.next=B,继续执行(我们这里既然讲的特殊,特殊化为扩容后A,B在newTable的索引任然相同)

e.next = newTable[i];
newTable[i] = e;
e = next;

4、线程一继续执行,e.next=newTable[i](i=4)(这e就是A)

因为线程二扩容完成newTable[i](newTable[4])= Entry B(这个B是已经完成线程二扩容的hashmap中的newTable第4号元素链表)

5、线程一继续执行:newTable[i] = e;(将A,头插入到B之前)

6、实际上并不是出现两个A,而是出现了环链

7、线程一继续执行:e=next(next = B,是在线程一等待之前的变量值)

8、线程一继续执行: while(B!=null),满足条件,(此时A,B已经是环链结构了)

            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;
            }

9、线程一继续执行: Entry<K,V> next = e.next;

变量情况:next = A, e = B

10、线程一继续执行: e.next = newTable[4],(即时B.next = newTable[4], 可以从图上图中看出来newTable[4]=A )

相当于B.next = A

11、线程一继续执行: newTable[i] = e; (即是 赋值newTable[4] = B),将B头插在链表链首位置

结构变成

12、线程一继续执行:e = next ; (e又变成了A)

while将会一直循环下去,形成死循环,不停增大JVM开销,最后内存溢出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值