`

HashMap安全性

阅读更多
Race Condition引起的性能问题


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



可是上个星期我却遇见了相反的情况:因为缺少同步标志也同样会使性能受影响。

那是一个ERP系统,运行在我们的T2000服务器(8核32线程)上。当500个并发用户的时候居然把所有的CPU都压得满满的(90%以上的忙碌)。这是很少有的现象,在我测试的所有项目中很少有扩展性这么好的系统能把T2000的32个线程都占满的。我狠狠的夸了他们的应用。话音没落,却发现测试结果很差,平均响应时间很长。不可能呀,所有的CPU都在干活,而且都在用户态(如果在系统态干太多的活就有问题了),结果怎么还会差呢。CPU都在干嘛呢?

通过工具发现(Dtrace for Java),我们发现很多的CPU都在做一件事情,那就是不停的执行一条Java语句(HashMap.get())。象是进入了死循环。我们进行了进一步试验,让并发用户数量为1,不停的运行10分钟,结果没有发现这种情况;接着我们让50个并发用户同时运行,但是只运行在一个CPU上(通过psrset),结果也没有出现死循环状态。只要并发用户数量超过10个,运行的CPU超过两个,不到2分钟就出现死循环。一旦死循环出现,大量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的时候加上同步标志,问题得到解决!
分享到:
评论

相关推荐

    关于如何解决HashMap线程安全问题的介绍

    总结起来,理解HashMap的线程不安全性及其潜在问题,并根据实际需求选择合适的安全措施,是确保Java程序稳定运行的关键。无论是使用Collections.synchronizedMap()、ConcurrentHashMap还是避免在多线程环境中使用,...

    高级程序员必会的HashMap的线程安全问题,适用于0~2年的.7z

    在实际开发中,选择哪种策略取决于具体场景,需要权衡线程安全性和性能需求。理解HashMap的线程安全问题,以及如何有效地解决这些问题,是每个高级程序员必备的技能,特别是对于0~2年经验的开发者来说,这是一项重要...

    hashmap面试题_hashmap_

    2. 可空性:键和值都可以为null,但一个HashMap只能有一个键为null的条目。 3. 默认容量:16,负载因子0.75,当容量达到负载因子乘以当前容量时,会发生扩容。 四、HashMap面试题解析 1. HashMap的初始容量和扩容...

    HashMap与HashTable区别

    它通过内部同步(synchronized)机制确保了多线程环境下的安全性。这意味着在多线程环境中,对`HashTable`的操作不会导致数据不一致的情况发生。 - **HashMap**: 默认是非线程安全的。如果多个线程同时访问一个`...

    HashMap的数据结构

    HashMap是Java编程语言中一个非常重要的数据结构,它...然而,根据具体应用的需求,可能需要考虑其线程安全性、内存占用以及在特定哈希函数下的性能表现等因素。理解HashMap的工作原理对于编写高效的Java代码至关重要。

    HashMap和HashTable的区别和不同

    线程安全性 - **HashTable**: `HashTable`是一个线程安全的类,这意味着多个线程可以同时访问或修改`HashTable`而不会导致数据不一致的问题。`HashTable`通过同步每个方法的执行来实现这一点,即在执行`HashTable`...

    枚举 HashMap

    虽然HashMap不是线程安全的,但在单线程环境下使用或配合同步机制(如`synchronized`关键字或`Collections.synchronizedMap()`)可以保证安全性。 以下是一个简单的示例,展示了如何用HashMap实现枚举功能: ```...

    hashMap和hashTable的区别

    2. **线程安全性**: - **HashMap**:默认情况下是非线程安全的,即不是同步的。如果多个线程同时访问一个 `HashMap` 实例,而其中至少一个线程修改了该 `HashMap` 结构,则必须保持外部同步。 - **HashTable**:...

    Java中HashMap详解(通俗易懂).doc

    5. **线程安全性**:HashMap本身不是线程安全的,如果在多线程环境中使用,需要外部同步机制来保证数据一致性。对于线程安全的需求,可以使用ConcurrentHashMap。 HashSet是基于HashMap实现的,它不存储值,只存储...

    HashMap类.rar

    5. **线程不安全**:HashMap不是线程安全的,如果在多线程环境中使用,需要外部同步机制,或者使用ConcurrentHashMap。 6. **null键与null值**:HashMap允许键和值为null,但只有一个键可以为null,且该键对应的值...

    hashtable和hashmap的区别

    ### Hashtable和HashMap的区别 在Java编程语言中,`Hashtable`和`HashMap`是两种非常重要的数据结构,它们都实现了`Map`接口,用于...通过权衡线程安全性和性能需求,可以更有效地利用这些数据结构来解决实际问题。

    简单的key value hashmap

    然而,由于其非线程安全的特性,对于多线程环境,通常需要考虑使用`ConcurrentHashMap`来保证并发访问的安全性。此外,还需注意内存占用,因为HashMap会存储键值对的引用,如果键或值是大对象,可能会导致内存消耗过...

    hashmap与hashtable区别

    线程安全性 - **Hashtable**:该类是线程安全的,即多个线程可以同时访问一个`Hashtable`对象而不会出现任何问题。这是因为它内部的方法都是同步化的(synchronized),这就意味着在多线程环境中使用`Hashtable`时...

    通过代码证明HashMap是线程不安全的(只用了一个Java文件)

    然而,`HashMap`在并发环境下并非线程安全。这个主题通常涉及到多线程编程和Java集合框架的基础知识。本篇文章将通过分析`HashMap`的源码以及编写一个简单的测试程序来证明这一点。 首先,我们要理解什么是线程安全...

    马士兵老师HashMap学习笔记

    为了避免这种情况,开发者需要在多线程环境下使用线程安全的数据结构,如ConcurrentHashMap,或者在单线程环境中确保put操作的原子性。 总的来说,马士兵老师的HashMap学习笔记不仅涵盖了HashMap的基础知识,还深入...

    ArrayList,HashMap

    ArrayList和HashMap是Java编程语言中两种非常重要的集合类,它们都是Java集合框架(Collections Framework)的一部分,用于存储和管理对象...在选择使用哪种数据结构时,应考虑其特性、性能需求以及线程安全性等因素。

    Hashtable和HashMap区别

    线程安全性 `Hashtable`的所有方法都是同步的,这意味着它可以在多线程环境下安全地使用,而不需要额外的同步控制。然而,这种同步机制也带来了性能上的开销。相比之下,`HashMap`是非线程安全的,它没有同步任何...

    HashMap类

    3. **线程安全性**:HashMap不是线程安全的,如果在多线程环境下使用,需要使用Collections.synchronizedMap()进行同步或者使用ConcurrentHashMap,后者是专门为并发设计的哈希映射表。 HashMap类的常见方法包括: ...

    【并发】为什么HashMap是线程不安全的?

    1.什么是线程安全性(what) 2.如何分辨一个类是否线程安全?(HOW) 3.为什么hashmap不安全 why 3.1 插入HashMap.put 3.1.1 HashMap 在扩容的时候 3.2 HashMap 在删除数据的时候 0.背景 经常会看到说HashMap是线程...

    hashmap.zip

    6. **线程安全性**:HashMap在JDK 1.7中是非线程安全的,这意味着在多线程环境下,不同线程同时操作HashMap可能导致数据不一致或异常。如果需要线程安全,可以使用ConcurrentHashMap。 7. **null键和值**:HashMap...

Global site tag (gtag.js) - Google Analytics