`
liujiahaogood
  • 浏览: 26137 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

HashMap在并发环境下的死循环分析[copy]

阅读更多

今天在看《分布式java应用》这本书的时候看到作者提到HashMap在多线程并发的环境下有可能出现死循环,导致cpu100%的现象,看了下源码结合网上的分析说明下这种可能性。可能出现问题的地方是在扩容的时候

  1. void resize(int newCapacity) {  
  2.         Entry[] oldTable = table;  
  3.         int oldCapacity = oldTable.length;  
  4.         if (oldCapacity == MAXIMUM_CAPACITY) {  
  5.             threshold = Integer.MAX_VALUE;  
  6.             return;  
  7.         }  
  8.   
  9.         Entry[] newTable = new Entry[newCapacity];  
  10.         transfer(newTable);  
  11.         table = newTable;  
  12.         threshold = (int)(newCapacity * loadFactor);  
  13.     }  

 

这个方法本身没有问题,问题出在transfer(newTable);这个方法是用来移动oldTable里的数据到newTable里。

  1. /** 
  2.     * Transfers all entries from current table to newTable. 
  3.     */  
  4.    void transfer(Entry[] newTable) {  
  5.        Entry[] src = table;  
  6.        int newCapacity = newTable.length;  
  7.        for (int j = 0; j < src.length; j++) {  
  8.         //(1)  
  9.            Entry<K,V> e = src[j];  
  10.            if (e != null) {  
  11.                src[j] = null;  
  12.                do {  
  13.                 //(2)  
  14.                    Entry<K,V> next = e.next;  
  15.                    int i = indexFor(e.hash, newCapacity);  
  16.                 //(3)  
  17.                    e.next = newTable[i];  
  18.                    newTable[i] = e;  
  19.                    e = next;  
  20.                } while (e != null);  
  21.            }  
  22.        }  
  23.    }  

 

下面分析可能出现的情况,假设原来table里存放的entry链表顺序是:

oldTable[i]:a1,a2,null

线程P1运行到(1)下面这行时,e=a1(a1.next=a2),执行到(2)下面时:next=e.next=a2。这个时候切换到线程P2,线程P2执行完这个链表的循环,如果刚好a1和a2在newTable里的i值相同(int i = indexFor(e.hash, newCapacity);),那么此时的链表顺序是:

newTable[i]:a2(next=a1),a1,null

现在cpu重新切回P1,在(3)这行:e.next = newTable[i];即:a1.next=newTable[i]=a2;

然后:newTable[i]=e=a1;e = next=a2;可以看到这个时候a1.next=a2,a2.next=a1,形成回环了,这样就造成了死循环.下面是针对各个线程各变量的情况

init(初始值):a1.next=a2,a2.next=null
 P1:e=a1,next=e.next=a2; waiting
 P2:a2.next=a1,a1.next=null ;notify
 P1:e.next=a1.next=newTable[i]=a2; newTable[i]=a1,e=next=a2
 end:a1.next=a2;a2.next=a1(P2结束后产生的结果)

可以看到很偶然的情况下会出现死循环,不过一旦出现后果是非常严重的,多线程的环境还是应该用ConcurrentHashMap。

分享到:
评论

相关推荐

    HashMap扩容死循环问题源码分析.mp4

    详 解 hashmap 1.7 扩 容 机 制 的 数 据 迁 移 以 及 出 现 环 形 列 表 导 致 死 锁 情 况 视 频

    疫苗:Java HashMap的死循环

    然而,在多线程环境中使用HashMap可能会导致死循环的问题。下面我们来分析HashMap的死循环原因。 首先,HashMap的数据结构是一个数组加链表的结构。每个数组元素是一个链表的头结点,每个链表节点包含了key-value对...

    并发下的 HashMap 为什么会引起死循环???.zip

    计算机技术、IT咨询、人工智能AI理论介绍,学习参考资料计算机技术、IT咨询、人工智能AI理论介绍,学习参考资料计算机技术、IT咨询、人工智能AI理论介绍,学习参考资料计算机技术、IT咨询、人工智能AI理论介绍,学习...

    java的hashMap多线程并发情况下扩容产生的死锁问题解决.docx

    此外,引入了ConcurrentHashMap类,这是一个专门为多线程设计的高效容器,其内部使用分段锁策略,可以在并发环境下保证线程安全,避免了类似HashMap扩容引发的死锁问题。 如果你在多线程环境中使用HashMap并遇到...

    深入了解JAVA HASHMAP的死循环

    首先,死循环问题通常发生在并发环境中,当多个线程同时修改HashMap时。HashMap的核心数据结构是一个数组(table[]),数组中的每个元素都是一个链表(Entry)。键值对通过哈希函数计算出其在数组中的位置,若存在...

    hashmap面试题_hashmap_

    面试中,可能会被问及HashMap的性能优化、内存占用分析、以及在特定场景下的选择,如并发环境、内存敏感的应用等。 总结,HashMap是Java编程中的基础工具,掌握其工作原理和常见面试题,不仅能帮助我们应对面试,更...

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

    在多线程环境下,两个线程同时触发扩容可能导致循环链表的形成,从而引发死循环,这是一种严重的性能问题。 为了解决HashMap的线程不安全问题,我们可以采取以下几种策略: 1. 使用Collections.synchronizedMap()...

    马士兵老师HashMap学习笔记

    总的来说,马士兵老师的HashMap学习笔记不仅涵盖了HashMap的基础知识,还深入探讨了其在不同JDK版本中的实现细节,特别是并发环境下的问题和解决方案。理解这些内容对于提升Java编程技能和优化代码性能具有重要价值...

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

    2. **数据不一致**:由于HashMap的内部实现,如resize操作,可能在并发环境下导致数据的不一致。例如,两个线程同时尝试扩容HashMap,可能会导致某些元素丢失或者被错误地放置到新的bucket中。 3. **死循环(死锁)...

    HashMap 分析

    在本分析中,我们将会详细探讨HashMap在不同负载因子(loadFactor)、循环次数(loop)、哈希表长度(maptablelen)和映射长度(maplen)等条件下的行为和特性。 负载因子(loadFactor)是HashMap中的一个关键参数...

    java HashMap原理分析

    Java HashMap原理分析 Java HashMap是一种基于哈希表的数据结构,它的存储原理是通过将Key-Value对存储在一个数组中,每个数组元素是一个链表,链表中的每个元素是一个Entry对象,Entry对象包含了Key、Value和指向...

    HashMap导致CPU100% 的分析

    HashMap导致CPU100% 的分析

    HashMap源码分析

    HashMap 是非线程安全的,这意味着在多线程环境下,如果不采取同步措施,可能会出现数据不一致的情况。如果需要线程安全的哈希表,可以使用其线程安全的版本:ConcurrentHashMap。 总的来说,HashMap 是通过数组和...

    ArrayList,HashMap

    此外,ArrayList和HashMap在并发环境下需要特别注意。如果不进行同步控制,多线程环境下可能会出现数据不一致的问题。对于并发场景,可以使用CopyOnWriteArrayList(线程安全的ArrayList变体)和ConcurrentHashMap...

    hashmap实现原理

    这是因为在HashMap中,`hashCode()`用于确定键对象在表中的位置,而`equals()`用于在链表中找到正确的键值对。默认的`hashCode()`方法返回的是对象的内存地址,而`equals()`仅检查两个对象是否指向同一个实例。如果...

    hashMap存储分析

    hashMap存储分析hashMap存储分析

    面试必考之HashMap源码分析与实现

    面试中,HashMap的源码分析与实现是一个常见的考察点,因为它涉及到数据结构、并发处理和性能优化等多个核心领域。本篇文章将深入探讨HashMap的内部工作原理、关键特性以及其在实际应用中的考量因素。 HashMap基于...

    HashMap与HashTable区别

    - **HashMap**: 相对于`HashTable`,`HashMap`在单线程或低并发情况下具有更好的性能。这是因为`HashMap`没有同步开销,因此操作速度更快。 #### 四、内部实现细节 - **HashTable**: 内部使用了`Entry`类来表示...

Global site tag (gtag.js) - Google Analytics