Race Condition 引起的 HashMap CPU100%

Race Condition(也叫做资源竞争),是多线程编程中比较头疼的问题。特别是Java多线程模型当中,经常会因为多个线程同时访问相同的共享数据,而造成数据的不一致性。为了解决这个问题,通常来说需要加上同步标志“synchronized”,来保证数据的串行访问。但是“synchronized”是个性能杀手,过多的使用会导致性能下降,特别是扩展性下降,使得你的系统不能使用多个CPU资源。


HashMap不是一个线程安全的数据结构,要用到多个线程中去,需要自己加上同步标志,为什么会死循环呢,看看下面HashMap中get函数的源代码:

public V get(Object key) {
 if (key == null)
     return getForNullKey();
        int hash = hash(key.hashCode());
        for (Entry<K,V> e = table[indexFor(hash, table.length)];
             e != null;
             e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
                return e.value;
        }
        return null;
    }

get函数会根据key的hashcode来锁定多个对象,并且遍历这些对象来找到key所对应的对象

当多个线程不安全的修改HanshMap数据结构的时候,有可能使得这个函数进入死循环。

我们建议客户使用ConcurrentHashMap或在使用HanshMap的时候加上同步标志

单步Debug是没问题,但代码在多线程情况下工作会出现线程安全。 Hashmap不是读写线程安全的,只有全部只读才是线程安全的,Hashmap在被并发读写使用的时候会出现线程安全问题,一般理解的线程安全问题导致的是数据错误。 而Hashmap多线程同时读写操作时,可能使程序挂起。

以下引用自http://sdh5724.javaeye.com/blog/619130

       分析: 我们知道Hashmap在被并发读写使用的时候, 会抛出ConcurrentModificationException这个异常, 但是JDK文档明确指出, 这个异常抛出是属于 fail-fast 的一个设计方法, 目的是为了开发者能及早的意识到线程安全问题发生。 但是, 这个fail-fast不是一定会发生, 而是可能会发生的行为。 因此, 在一个不确定状态下的下,jvm线程发生持续100%cpu行为是比较容易理解了(for (Entry<K,V> e = table[i]; e != null; e = e.next), 目前只能估计是这个代码进入死循环的状态,还不能非常明确)。

“正确用法”

注意更改HashMap中的内容时是否存在同时并发线程读的情况,如果有, 需要对读写的入口做同步. 如果知道要在多线程情况下读写Map, 建议使用线程安全的ConcurrentHashMap实现代替HashMap。ConcurrentHashMap 可以在不损失线程安全的同时提供很好的并发性。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值