面试——HashMap的并发问题

server/2024/11/30 1:42:32/

HashMap是线程不安全,在并发使用HashMap时会发生下列问题:

  1. 数据丢失
    HashMap底层数据结构为数组,之后如果发送了哈希冲突,那么数据会以列表的形式保存在这个下标下,当数据长度大于8时,则会转为红黑树。
    在这里插入图片描述
    存在这样一个场景,同时进来两个元素,且保存下标也为同一个,此时下标下的末尾指向的元素就会是两个,就会有一个数据被覆盖掉,导致了数据丢失。
    下面通过代码进行场景复现:
java">public static void test1() throws InterruptedException {HashMap<String, Integer> map = new HashMap<>();// 定义五个线程Thread[] threads = new Thread[5];// 往每个线程添加200条数据for (int i = 0; i<5; i++){int finalI = i;threads[i] = new Thread(() -> {for (int j = 0; j<200; j++){map.put(finalI + "_" + j, j);}});threads[i].start();}for (int i = 0; i<5; i++){threads[i].join();}// 最后输出Map中数据的数量System.out.println(map.size());}

输出结果(正确数量应该为1000):

java">905
  1. 数据结构转换异常
    前面说过,若下标下列表过长,则会转化为红黑树进行扩容。那么就会存在这样一个场景,有两个线程,线程一往HashMap中的某个下标添加数据时,此时还没到达扩容临界点,还是以列表的结构去添加数据,线程二同时也往这个下标添加数据,但此时列表长度大于临界点了,发送了扩容,结构变成了红黑树,那么线程一还是以数组结构去添加数据,则会报错了。
    下面通过代码进行场景复现:
java">public static void test2() throws InterruptedException {while (true){HashMap<String, Integer> map = new HashMap<>();// 定义五个线程Thread[] threads = new Thread[5];// 往每个线程添加200条数据for (int i = 0; i<5; i++){int finalI = i;threads[i] = new Thread(() -> {for (int j = 0; j<200; j++){map.put(finalI + "_" + j, j);}});threads[i].start();}for (int i = 0; i<5; i++){threads[i].join();}// 最后输出Map中数据的数量System.out.println(map.size());Thread.sleep(100);}}

输出结果:

java">Exception in thread "Thread-147800" Exception in thread "Thread-147803" java.lang.ClassCastException: java.util.HashMap$Node cannot be cast to java.util.HashMap$TreeNodeat java.util.HashMap$TreeNode.moveRootToFront(HashMap.java:1835)at java.util.HashMap$TreeNode.putTreeVal(HashMap.java:2014)at java.util.HashMap.putVal(HashMap.java:638)at java.util.HashMap.put(HashMap.java:612)at com.ooamo.test.HashMapTest.lambda$test2$1(HashMapTest.java:42)at java.lang.Thread.run(Thread.java:748)
java.lang.ClassCastException: java.util.HashMap$Node cannot be cast to java.util.HashMap$TreeNodeat java.util.HashMap$TreeNode.moveRootToFront(HashMap.java:1835)at java.util.HashMap$TreeNode.treeify(HashMap.java:1951)at java.util.HashMap.treeifyBin(HashMap.java:772)at java.util.HashMap.putVal(HashMap.java:644)at java.util.HashMap.put(HashMap.java:612)at com.ooamo.test.HashMapTest.lambda$test2$1(HashMapTest.java:42)at java.lang.Thread.run(Thread.java:748)
  1. 发生死列
    这个问题是在HashMap1.7的时候才会发送,因为HashMap之前使用的是头插法进行数据插入,所以在并发执行的过程中可能会出现节点的指向发生了改动。
    在这里插入图片描述
new->next = Head->next;
Head->next = new;

http://www.ppmy.cn/server/146043.html

相关文章

微信小程序全局配置:TabBar与页面配置详解

微信小程序全局配置:TabBar与页面配置详解 引言 随着移动互联网的迅猛发展,微信小程序作为一种新兴的应用形式,因其便捷性和丰富的功能而受到广泛欢迎。在小程序的开发过程中,全局配置是非常重要的一环,尤其是tabBar和页面的配置。本文将深入探讨微信小程序的全局配置,…

霍夫变换:原理剖析与 OpenCV 应用实例

简介&#xff1a;本文围绕霍夫变换相关内容展开&#xff0c;先是讲解霍夫变换基本原理&#xff0c;包含从 xy 坐标系到 kb 坐标系及极坐标系的映射等。接着介绍了 cv2.HoughLines、cv2.HoughLinesP 概率霍夫变换、cv2.HoughCircles 霍夫圆变换的函数用法、参数含义、与常规霍夫…

Diff差异算法

目录 虚拟DOM Diff算法 Diff过程 示例 总结 在Vue.js中&#xff0c;虚拟DOM&#xff08;Virtual DOM&#xff09;是其核心特性之一&#xff0c;它极大地提高了DOM更新的效率。Vue.js使用虚拟DOM的diff算法来比较新旧虚拟DOM树&#xff0c;从而确定最小的DOM更新操作。这种…

2024年11月27日Github流行趋势

项目名称&#xff1a;screenshot-to-code 项目维护者&#xff1a;abi clean99 sweep-ai kachbit vagusX项目介绍&#xff1a;通过上传截图将其转换为整洁的代码&#xff08;支持HTML/Tailwind/React/Vue&#xff09;。项目star数&#xff1a;62,429项目fork数&#xff1a;7,614…

学成在线day06

上传视屏 断点续传 通常视频文件都比较大&#xff0c;所以对于媒资系统上传文件的需求要满足大文件的上传要求。http协议本身对上传文件大小没有限制&#xff0c;但是客户的网络环境质量、电脑硬件环境等参差不齐&#xff0c;如果一个大文件快上传完了网断了没有上传完成&…

SpringBoot架构下宠物领养解决方案

第1章 绪论 1.1 课题背景 二十一世纪互联网的出现&#xff0c;改变了几千年以来人们的生活&#xff0c;不仅仅是生活物资的丰富&#xff0c;还有精神层次的丰富。时代进步的标志&#xff0c;就是让人们过上更好的生活。在互联网诞生之前&#xff0c;地域位置往往是人们思想上不…

MySQL:常用数据类型

专栏说明&#xff1a;本专栏用于MySQL学习&#xff0c;如对你学习有所帮助&#xff0c;可以点赞收藏关注&#xff0c;感谢三连。 博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;MySQL数据库关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出…

ABAP 快速入门之 Hello World 和 ALV 列表

ABAP 是 SAP 开发的一种编程语言&#xff0c;用于在 SAP 环境中对业务应用程序进行编程。得益于 ABAP 对象增强功能&#xff0c;ABAP 以前只是过程性语言&#xff0c;现在也是一种面向对象语言。 ABAP 750 文档&#xff1a;ABAP Keyword Documentation (sap.com) Hello World…