多线程环境下HashMap之死循环

本文探讨了为什么HashMap在多线程环境下可能导致死循环,并详细解析了ConcurrentHashMap在JDK1.6中如何通过锁机制解决这一问题。尽管JDK1.8已修复该问题,但HashMap仍不是线程安全的选择。文中还深入分析了JDK1.8中resize操作的改进,避免了循环链表的产生。
摘要由CSDN通过智能技术生成

多线程环境下HashMap之死循环


众所周知,HashMap是非线程安全的,多线程下一般使用ConcurrentHashMap代替,那为什么HashMap在多线程下不安全呢?ConcurrentHashMap又是如何改进的?

为什么HashMap在多线程先不安全

HashMap 在多线程环境下可能会发生死循环

看过HashMap(jdk1.6)的put方法源码的人都知道,在put数据时有可能会触发table表的扩容,调用的方法是resize方法,在resize方法中会新建一个更大的hash表,然后将老的的数据迁移到新表中,迁移时用到的方法是transfer,下面附上transfer方法的源代码:

void transfer(Entry[] newTable)
{
    Entry[] src = table;
    int newCapacity = newTable.length;
    for(intj = 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);
        }
    }
}

现在有俩个线程,在put时都触发了扩容机制,线程一执行到标记①挂起了,此时的hash表情况如下:
这里写图片描述
线程二继续执行,两轮循环后:
这里写图片描述
此时线程二挂起,线程一继续执行:
这里写图片描述
线程一执行一轮循环后:
这里写图片描述

此时出现了循环链表,线程一陷入死循环,所以HashMap不适合在多线程场景下使用。

ConcurrentHashMap(jdk1.6)又是如何改进的

V put(K key, int hash, V value, boolean onlyIfAbsent) {
            //标记①
            lock();
            try {
                int c = count;
                if (c++ > threshold) // ensure capacity
                    rehash();
                HashEntry<K,V>[] tab = table;
                int index = hash & (tab.length - 1);
                HashEntry<K,V> first = tab[in
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值