HashMap在高并发下引起的死循环

HashMap其实并不是线程安全的,在高并发的情况下,是很可能发生死循环的,由此造成CPU 100%,这是很可怕的,所以在多线程的情况下,用HashMap是很不妥当的行为,应采用线程安全类ConcurrentHashMap进行代替。

HashMap死循环原因

HashMap进行存储时,如果size超过当前最大容量*负载因子时候会发生resize,首先看一下resize原代码

void resize(int newCapacity) {
        Entry[] oldTable = table;
        int oldCapacity = oldTable.length;
        if (oldCapacity == MAXIMUM_CAPACITY) {
            threshold = Integer.MAX_VALUE;
            return;
        }

        Entry[] newTable = new Entry[newCapacity];
        transfer(newTable);
        table = newTable;
        threshold = (int)(newCapacity * loadFactor);
    }

而这段代码中又调用了transfer()方法,而这个方法实现的机制就是将每个链表转化到新链表,并且链表中的位置发生反转,而这在多线程情况下是很容易造成链表回路,从而发生get()死循环,我们看一下他的源代码

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

HashMap死循环演示

假如有两个线程P1、P2,以及链表 a=》b=》null

1、P1先执行,执行完"Entry<K,V> next = e.next;"代码后发生阻塞,或者其他情况不再执行下去,此时e=a,next=b

2、而P2已经执行完整段代码,于是当前的新链表newTable[i]为b=》a=》null

3、P1又继续执行"Entry<K,V> next = e.next;"之后的代码,则执行完"e=next;"后,newTable[i]为a《=》b,则造成回路,while(e!=null)一直死循环

总结

HashMap并非线程安全,所以在多线程情况下,应该首先考虑用ConcurrentHashMap,避免悲剧的发生

时间: 2024-10-13 01:57:01

HashMap在高并发下引起的死循环的相关文章

HashMap在高并发下如果没有处理线程安全会有怎样的安全隐患,具体表现是什么

Hashmap在并发环境下,可能出现的问题: 1.多线程put时可能会导致get无限循环,具体表现为CPU使用率100%: 原因:在向HashMap put元素时,会检查HashMap的容量是否足够,如果不足,则会新建一个比原来容量大两倍的Hash表,然后把数组从老的Hash表中迁移到新的Hash表中,迁移的过程就是一个rehash()的过程,多个线程同时操作就有可能会形成循环链表,所以在使用get()时,就会出现Infinite Loop的情况 // tranfer()片段 // 这是在res

高并发下,HashMap会产生哪些问题?

HashMap在高并发环境下会产生的问题 HashMap其实并不是线程安全的,在高并发的情况下,会产生并发引起的问题: 比如: HashMap死循环,造成CPU100%负载 触发fail-fast 下面逐个分析下出现上述情况的原因: HashMap死循环的原因 HashMap进行存储时,如果size超过(当前最大容量*负载因子)时候会发生resize,首先看一下resize源代码: void resize(int newCapacity) { Entry[] oldTable = table;

高并发下的Java数据结构(List,Set,Map,Queue)

由于并行程序与串行程序的不同特点,适用于串行程序的一些数据结构可能无法直接在并发环境下正常工作,这是因为这些数据结构不是线程安全的.本节将着重介绍一些可以用于多线程环境的数据结构,如并发List.并发Set.并发Map等. 1.并发List Vector 或者 CopyOnWriteArrayList 是两个线程安全的List实现,ArrayList 不是线程安全的.因此,应该尽量避免在多线程环境中使用ArrayList.如果因为某些原因必须使用的,则需要使用Collections.synchr

php结合redis实现高并发下的抢购、秒杀功能

原文: http://blog.csdn.net/nuli888/article/details/51865401 抢购.秒杀是如今很常见的一个应用场景,主要需要解决的问题有两个:1 高并发对数据库产生的压力2 竞争状态下如何解决库存的正确减少("超卖"问题)对于第一个问题,已经很容易想到用缓存来处理抢购,避免直接操作数据库,例如使用Redis.重点在于第二个问题 常规写法: 查询出对应商品的库存,看是否大于0,然后执行生成订单等操作,但是在判断库存是否大于0处,如果在高并发下就会有问

高并发下的 Nginx 优化与负载均衡

高并发下的 Nginx 优化 英文原文:Optimizing Nginx for High Traffic Loads 过去谈过一些关于Nginx的常见问题; 其中有一些是关于如何优化Nginx. 很多Nginx新用户是从Apache迁移过来的,因些他们过去常常调整配置和执行魔术操作来确保服务器高效运行. 有一些坏消息要告诉你, 你不能像Apache一样优化Nginx.它没有魔术配置来减半负载或是让PHP运行速度加快一倍. 高兴的是, Nginx已经优化的非常好了. 当你决定使用Nginx并用a

高并发下的Nginx优化

高并发下的Nginx优化 2014-08-08 13:30 mood Nginx 过去谈过一些关于Nginx的常见问题; 其中有一些是关于如何优化Nginx. 很多Nginx新用户是从Apache迁移过来的,因些他们过去常常调整配置和执行魔术操作来确保服务器高效运行. AD:2014WOT全球软件技术峰会北京站 课程视频发布 11月21日-22日 与WOT技术大会相约深圳 现在抢票 过去谈过一些关于Nginx的常见问题; 其中有一些是关于如何优化Nginx. 很多Nginx新用户是从Apache

php 结合redis实现高并发下的抢购、秒杀功能

抢购.秒杀是如今很常见的一个应用场景,主要需要解决的问题有两个:1 高并发对数据库产生的压力2 竞争状态下如何解决库存的正确减少("超卖"问题)对于第一个问题,已经很容易想到用缓存来处理抢购,避免直接操作数据库,例如使用Redis.重点在于第二个问题 常规写法: 查询出对应商品的库存,看是否大于0,然后执行生成订单等操作,但是在判断库存是否大于0处,如果在高并发下就会有问题,导致库存量出现负数 [php] view plain copy <?php $conn=mysql_con

(高级篇)php结合redis实现高并发下的抢购、秒杀功能

抢购.秒杀是如今很常见的一个应用场景,主要需要解决的问题有两个:1 高并发对数据库产生的压力2 竞争状态下如何解决库存的正确减少("超卖"问题)对于第一个问题,已经很容易想到用缓存来处理抢购,避免直接操作数据库,例如使用Redis.重点在于第二个问题 常规写法: 查询出对应商品的库存,看是否大于0,然后执行生成订单等操作,但是在判断库存是否大于0处,如果在高并发下就会有问题,导致库存量出现负数 优化方案1:将库存字段number字段设为unsigned,当库存为0时,因为字段不能为负数

高并发下linux系统、业务结构性能优化——index(不断更新)

工作中零零散散写了些博客,总结了些知识,当然是从运维的角度.东西一多就乱,闲时突发奇想,这些东西能不能打在一个点上,如果能有一个东西把所有内容串起来并且有一个主题岂不妙哉,也方便查阅和阅读,就像一个网站有了内容后需要一个index主页一样,哈哈,然后就有了这篇置顶博文. 对于主题,我喜欢研究业务架构和大并发相关知识,就定为"高并发下linux系统.业务结构性能优化"了,现有目录结构是根据工作经验进行的梳理,以后会动态修改.我的知识非常有限,不乏有些错误认识,不管怎样抛砖引玉分享出来,希