栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

HashMap的线程不安全问题

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

HashMap的线程不安全问题

文章目录
    • 一. HashMap的线程不安全问题概述
      • 1. 数据覆盖导致元素丢失
      • 2. 读出null值
      • 3. 死循环
      • 参考资料


一. HashMap的线程不安全问题概述
  • 多线程下HashMap的线程不安全问题总结
JDK7JDK8
1.数据覆盖造成的元素丢失(场景:put扩容+put扩容)
2.读出为null(场景:put时扩容+get)
3.死循环 (场景:多线程扩容时,头插法导致链表形成环,造成死循环)
1.数据覆盖造成的元素丢失(场景:put扩容+put扩容)
2.读出为null(场景:put时扩容+get)
3.不会发生死循环(因为是尾插法)
  • HashMap 存在线程安全的本质:HashMap的"增删改"操作均是多步操作的集合,或者说是非原子的。在多线程环境下,非原子的操作可能因为线程调度的问题,引发各种线程不安全性问题。死循环和丢失更新只是其中最具代表的线程不安全表现。
1. 数据覆盖导致元素丢失

JDK7和JDK8都存在这个问题

  1. 概述:两个线程同时执行put操作,如果计算出的索引位置相同(即哈希冲突)且该索引位置为空,则会造成前一个key被后一个key覆盖,从而导致元素丢失。
  2. 核心代码:put()方法
put(K key, V value);
putVal(hash(key), key, value, false, true);

final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
    Node[] tab; Node p; int n, i;
    if ((tab = table) == null || (n = tab.length) == 0)
        n = (tab = resize()).length;
    if ((p = tab[i = (n - 1) & hash]) == null)           // 1
        tab[i] = newNode(hash, key, value, null);
    else {                                           
        //...
    }
    if (++size > threshold)  
        resize();
    return null;
}

  1. 场景解读
    1. 假设两个线程A、B都在进行put操作,并且通过hash计算出的插入下标相同。
    2. 当线程A执行完“// 1”处的代码后由于时间片耗尽导致被挂起,而线程B得到时间片后在该下标处插入了元素,完成了正常的插入。
    3. 然后,线程A获得时间片,由于之前已经进行了hash冲突的判断,所有此时不会再进行判断,而是直接进行插入,这就导致了线程B插入的数据被线程A覆盖了,从而线程不安全。
2. 读出null值

JDK7和JDK8都存在这个问题

  1. 概述:线程1进行put时,由于元素个数超出threshold而导致扩容,扩容方法里刚new出一个新的hash表,赋值给table,还没进行数据转移,此时线程2进行get,有可能导致读出为null(因为新hash表还没有值)。
  2. 核心源码
transient Node[] table;
final Node[] resize() {
  	//...
  	// 使用新计算的容量new出一个新的hash表
    Node[] newTab = (Node[])new Node[newCap];
    // 将新创建的空hash表赋值给实例变量table
    table = newTab;  // 1
    
    //...将数据从旧hash表转移到新hash表
    
    return newTab;
}
  1. 源码解读:如果线程1执行put操作扩容,在执行完第1行之后被挂起,此时实例变量table是空的。然后线程2执行get,就会得到null值。
3. 死循环

只有JDK7存在,JDK8不存在

参考资料
  • 一文教会你HashMap为啥线程不安全(多图VIP版)
  • Java–HashMap–线程不安全的原因/保证线程安全的方法–方案/实例
  • 常见面试题:HashMap线程不安全怎么办?
  • hashmap不安全例子,arraylist不安全例子
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/963386.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号