HashMap多线程下的问题

Java的文档说HashMap是非线程安全的,应该用ConcurrentHashMap。那么HashMap在多线程环境下会出现什么问题呢?

  1. 多线程put,get时出现死循环,导致CPU利用率过高
  2. 多线程put,可能导致元素丢失
  3. put非null元素后get出来的却是null

以上情况是怎么产生的?

1.多线程put,get时出现死循环,导致CPU利用率过高

1.CPU利用率过高一般是因为出现了出现了死循环,导致部分线程一直运行,占用cpu时间。问题原因就是HashMap是非线程安全的,多个线程put的时候造成了某个key值Entry key List的死循环。大量线程被hang住可能导致服务器宕机。

循环链表出现的原理分析:

(网上很多例子,这里就不举例了)
  参考:http://www.voidcn.com/article/p-hcuguoxo-bob.html

循环的产生是因为新链表的顺序跟旧的链表是完全相反的,所以只要保证建新链时还是按照原来的顺序的话就不会产生循环。

JDK8是用 head 和 tail 来保证链表的顺序和之前一样,这样就不会产生循环引用。

JDK8如何进行扩容参考《HashMap底层原理》

2:多线程put,可能导致元素丢失

主要问题出在addEntry方法的new Entry<K,V>(hash, key, value, e),如果两个线程都同时取得了e,则他们下一个元素都是e,然后赋值给table元素的时候有一个成功有一个丢失。

void addEntry(int hash, K key, V value, int bucketIndex)
{
    Entry<K,V> e = table[bucketIndex];
    table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
    //查看当前的size是否超过了我们设定的阈值threshold,如果超过,需要resize
    if (size++ >= threshold)
        resize(2 * table.length);
}

3:put非null元素后get出来的却是null

在transfer方法中代码如下:

void transfer(Entry[] newTable) {
    Entry[] src = table;
    int newCapacity = newTable.length;
    for (int j = 0; j < src.length; j++) {
        Entry e = src[j];
        if (e != null) {
            src[j] = null;
            do {
                Entry next = e.next;
                int i = indexFor(e.hash, newCapacity);
                e.next = newTable[i];
                newTable[i] = e;
                e = next;
            } while (e != null);
        }
    }
}

在这个方法里,将旧数组赋值给src,遍历src,当src的元素非null时,就将src中的该元素置null,即将旧数组中的元素置null了:

if (e != null) {
        src[j] = null;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 在一个方法内部定义的变量都存储在栈中,当这个函数运行结束后,其对应的栈就会被回收,此时,在其方法体中定义的变量将不...
    Y了个J阅读 4,445评论 1 14
  • 摘要 HashMap是Java程序员使用频率最高的用于映射(键值对)处理的数据类型。随着JDK(Java Deve...
    周二倩你一生阅读 1,268评论 0 5
  • 那一年,杏花微雨,果郡王邂逅了自己的爱情。 于是,我盼一场杏花微雨,也想邂逅爱情邂逅你。 终于,我盼来了十里杏花。...
    田园执笔阅读 914评论 0 0
  • 一段小引子| 听了一段广播,讲了一个19岁少年短暂一生的故事,他的故事发生在贫苦闭塞远离城市的地方。 少年文章写的...
    药引子阅读 145评论 0 0
  • 有时候,当你不知道未来在哪,不如停下来,整理一下自己。 流年住的客人,大部分都是90后,这两年里真的是频繁接触90...
    逸小文阅读 857评论 0 0