HashMap为什么线程不安全?
一、Put操作(数据覆盖)
HashMap
底层是基于数组 + 链表(在 Java 8 以后,当链表长度超过一定阈值时会转换为红黑树)的数据结构。在多线程环境下,当多个线程同时对HashMap
进行put
操作时,可下面这种情况:
假设两个线程 A 和 B 同时执行put
操作,它们计算出的插入位置相同(假设为index
)。线程 A 先获取到了当前index
位置的节点,在它还没来得及将新节点插入链表(或树)时,线程 B 也获取到了这个位置的节点。然后线程 A 完成插入操作,接着线程 B 也执行插入操作,这就可能导致线程 B 插入的节点覆盖了线程 A 插入的节点,从而丢失数据,如下图。
二、扩容机制产生的问题
HashMap
在元素个数达到一定阈值(loadFactor * capacity
)时会进行扩容。扩容过程是一个比较复杂的操作,它涉及到重新计算每个元素的hash
值和新的存储位置,hashmap扩容采用的是头插法。
2.1 数据访问不一致
在多线程环境下,假设线程 A 正在进行扩容操作,此时线程 B 也在对HashMap
进行put
操作。由于扩容操作会重新分配数组空间并迁移元素,线程 B 可能会在这个过程中访问到不一致的数据结构。比如,线程 B 可能会读取到还没有完全迁移好的数据,或者在数据迁移过程中出现数据丢失或重复插入等情况。
假设第一次的原表如下:
这时A抢到时间片进入执行,并扩容:
2.2 循环引用问题
在并发环境中,假设有两个线程 A 和 B 同时对 HashMap 进行操作。线程 A 开始进行扩容操作,在遍历旧数组元素的过程中,还没有完成所有元素的重新放置。此时线程 B 也在对这个 HashMap 进行操作,可能会修改元素之间的引用关系。
比如:线程B
在遍历过程中完成了整个链表的重新分配,改变了链表的结构。然后线程A
继续执行,由于它之前取出了节点1,根据旧的引用关系来插入节点1,但是此时链表结构已经被线程B
改变。可能会出现节点1的next
指针又重新指向了已经处理过的节点,从而形成一个环形链表。
当后续在对这个 HashMap 进行操作(如get
操作),在遍历链表查找元素时,就会陷入这个环形链表的无限循环中,导致程序无法正常运行,这就是多线程扩容导致的死循环问题。
循环引用会导致这些节点无法被垃圾回收。因为垃圾回收器在进行可达性分析时,会发现从根对象出发可以通过引用链一直访问到这些节点,即使它们在逻辑上可能已经不再被程序正常使用,但由于循环引用的存在,它们依然被判定为可达对象,从而无法被回收,产生内存泄漏。
相关文章:

HashMap为什么线程不安全?
一、Put操作(数据覆盖) HashMap底层是基于数组 链表(在 Java 8 以后,当链表长度超过一定阈值时会转换为红黑树)的数据结构。在多线程环境下,当多个线程同时对HashMap进行put操作时,可下面这种…...

类加载器及反射
目录 1.类加载器 1.1类加载【理解】 1.2类加载器【理解】 1.2.1类加载器的作用 1.2.2JVM的类加载机制 1.2.3Java中的内置类加载器 1.2.4ClassLoader 中的两个方法 2.反射 2.1反射的概述【理解】 2.2获取Class类对象的三种方式【应用】 2.2.1三种方式分类 2.2.2示例…...

aws boto3 下载文件
起因:有下载 aws s3 需求,但只有web 登录账号,有 id 用户名 密码,没有 boto3 的 key ID 经过分析,发现网页版有个地址会返回临时 keyID,playwright 模拟登录,用 page.on 监测返回数据ÿ…...

3DDFA-V3——基于人脸分割几何信息指导下的三维人脸重建
1. 研究背景 从二维图像中重建三维人脸是计算机视觉研究的一项关键任务。在虚拟现实、医疗美容、计算机生成图像等领域中,研究人员通常依赖三维可变形模型(3DMM)进行人脸重建,以定位面部特征和捕捉表情。然而,现有的方…...

求串长(不使用任何字符串库函数)
问题描述 编写一个程序,输入一个字符串,输出串的长度。 要求: (1)字符串长度不超过100个字符。 (2)不使用任何字符串库函数,建议使用堆串存储结构。 输入描述 输入一个字符串。 …...

第02章 MySQL环境搭建
一、MySQL的卸载 如果安装mysql时出现问题,则需要将mysql卸载干净再重新安装。如果卸载不干净,仍然会报错安装不成功。 步骤1:停止MySQL服务 在卸载之前,先停止MySQL8.0的服务。按键盘上的“Ctrl Alt Delete”组合键࿰…...

linux系统编程 man查看manual.stat
获取文件属性,(从inode结构体中获取) stat/lstat 函数 int stat(const char *path, struct stat *buf); 参数: path: 文件路径 buf:(传出参数) 存放文件属性,inode结构体…...

从网络到缓存:在Android中高效管理图片加载
文章目录 在Android应用中实现图片缓存和下载项目结构使用 代码解析关键功能解析1. 图片加载方法2. 下载图片3. 保存图片到缓存4. 文件名提取 总结 首先我们需要在配置AndroidManifest.xml里面添加 <uses-permission android:name"android.permission.INTERNET" …...

【数据结构】链表详解:数据节点的链接原理
链表(Linked List)是一种基础的数据结构,是程序设计中用来存储数据的典型方法之一。链表特别适合插入和删除操作频繁的场景,是了解数据结构和算法的基础。本文将从零开始,带大家了解链表的底层原理、类型(单…...

使用AWS Redshift从AWS MSK中读取数据
Amazon Redshift 流式摄取的目的是简化将流式数据直接从流式服务摄取到 Amazon Redshift 或 Amazon Redshift Serverless 的过程。 官方文档[1]中有详细步骤。用unauthenticated, IAM 的方式均可以进行连接,只不过使用的是不同端口:9092或者9098 [1] h…...

从0开始学统计-数据类别与测量层次
数据分析前,我们首先要弄清楚数据的分类。数据并不仅仅是一堆数字和文字,它们实际上代表了我们看待事物属性的不同视角。从最宽泛的角度出发,我们可以将数据划分为定量(比如用数字表示)或者定性(例如&#…...

使用AIM对SAP PO核心指标的自动化巡检监控
一、背景 由于SAP PO系统维护成本较高,各类型异常报错等都需要人员进行时刻监控和响应,遂由AIM平台进行自动化巡检SAP PO的各指标,然后告警通知用户,节省维护成本和提高工作效率 二、核心指标监控 SAP PO失败消息 适用于S…...

C++——unordered_map和unordered_set的封装
unordered_map和unordered_set的底层结构用到的都是在哈希表模拟实现中的哈希桶的实现方式,哈希桶的具体实现我已经在哈希表的模拟实现里做过详细的介绍,这边会引用里面的代码进行改造和封装,同时为了方便操作,同样我采用二倍扩容…...

微信小程序scroll-view吸顶css样式化表格的表头及iOS上下滑动表头的颜色覆盖、z-index应用及性能分析
微信小程序scroll-view吸顶css样式化表格的表头及iOS上下滑动表头的颜色覆盖、z-index应用及性能分析 目录 微信小程序scroll-view吸顶css样式化表格的表头及iOS上下滑动表头的颜色覆盖、z-index应用及性能分析 1、iOS在scroll-view内部上下滑动吸顶的现象 正常的上下滑动吸顶…...

【高中数学】数列
等差数列前 n n n 项和性质 公式一: S n n ( a 1 a n ) 2 S_n\frac{n(a_1a_n)}{2} Sn2n(a1an) 公式二: S n n a 1 n ( n − 1 ) 2 d S_nna_1\frac{n(n-1)}{2}d Snna12n(n−1)d 性质1:等差数列中依次 k k k 项之和 S …...

数字媒体技术基础:AMF(ACES 元数据文件 )
在现代电影和电视制作中,色彩管理变得越来越重要。ACES(Academy Color Encoding System,美国电影艺术与科学学院颜色编码系统)是一个广泛采用的色彩管理和交换系统,旨在解决不同设备、软件和工作流程之间的色彩不一致问…...

Apache Dubbo (RPC框架)
本文参考官方文档:Apache Dubbo 1. Dubbo 简介与核心功能 Apache Dubbo 是一个高性能、轻量级的开源Java RPC框架,用于快速开发高性能的服务。它提供了服务的注册、发现、调用、监控等核心功能,以及负载均衡、流量控制、服务降级等高级功能。…...
LeetCode 3226. 使两个整数相等的位更改次数
. - 力扣(LeetCode) 题目 给你两个正整数 n 和 k。你可以选择 n 的 二进制表示 中任意一个值为 1 的位,并将其改为 0。 返回使得 n 等于 k 所需要的更改次数。如果无法实现,返回 -1。 示例 1: 输入: n …...

面试经典 150 题:189、383
189. 轮转数组 【参考代码】 class Solution { public:void rotate(vector<int>& nums, int k) {int size nums.size();if(1 size){return;}vector<int> temp(size);//k k % size;for(int i0; i<size; i){temp[(i k) % size] nums[i];}nums temp; }…...

Python模拟真人动态生成鼠标滑动路径
一.简介 鼠标轨迹算法是一种模拟人类鼠标操作的程序,它能够模拟出自然而真实的鼠标移动路径。 鼠标轨迹算法的底层实现采用C/C语言,原因在于C/C提供了高性能的执行能力和直接访问操作系统底层资源的能力。 鼠标轨迹算法具有以下优势: 模拟…...

如何压缩pdf文件的大小?5分钟压缩pdf的方法推荐
如何压缩pdf文件的大小?在现代办公和学习中,PDF文件因其稳定性和广泛的兼容性被广泛使用。然而,随着文件内容的增多,制作好的PDF文件常常变得过大,给使用带来了诸多不便。无论是电子邮件附件的发送,还是在线…...

【SQL】[2BP01] ERROR: cannot drop table course because other objects depend on it
问题描述 在尝试执行以下SQL语句时,发生错误。 DROP TABLE Course RESTRICT;执行以上语句后,系统返回了一个错误提示: [2BP01] ERROR: cannot drop table course because other objects depend on it 详细:constraint sc_cno_…...

gbase8s之spring框架用druid中间件报语法错误
spring框架 调用druid中间件 时报这个错: MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception …...

【网络安全】|nessus使用
1、扫描结果分析: Sev:漏洞的严重性级别 CVSS:量化漏洞严重性的标准,通过计算得出一个分数,分数越高表示漏洞越严重。 VPR:基于风险的评分系统,帮助组织优先处理风险最高的漏洞。 EPSS…...

CSRA2的LINUX操作系统24年11月2日上午上课笔记
几个查找命令: .whereis:查看文件的路径,查看可执行文件的路径,一级相应文档路径。 .which:查看系统可执行的文件的路径,以及命令的别名等信息 .local:他会将linux中的所有文件的路径信息保存到数据库中,在数据库中查…...

通过分解质因数求若干个数的最小公倍数
求最小公倍数的常规方法回顾 暴力枚举法 long long work(long long a,long long b) {for(long long imax(a,b);;i)if(i%a0&&i%b0)return i; }大数翻倍法 long long work(long long a,long long b) {if(a<b) swap(a,b);for(long long ia;;ia) // i 是 a 的倍数&#…...

数据库三范式(1NF、2NF、3NF)
1NF(第一范式) 定义:确保每一列都是原子值,即是不可分割的基础数据项。 所谓第一范式(1NF)是指在关系模型中,对于添加列的一个规范要求,所有的列都 应该是原子性的,即数…...

C语言_数据结构_顺序表
1. 本章重点 顺序表初始化顺序表尾插顺序表尾删顺序表头插顺序表头删顺序表查找顺序表在pos位置插入x顺序表删除pos位置的值顺序表销毁顺序表打印 2. 顺序表的概念及结构 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储…...

Llama 3.2 Vision Molmo:多模态开源生态系统基础
编者按: 视觉功能的融入对模型能力和推理方式的影响如何?当我们需要一个既能看懂图像、又能生成文本的 AI 助手时,是否只能依赖于 GPT-4V 这样的闭源解决方案? 我们今天为大家分享的这篇文章,作者的核心观点是…...

【数据结构与算法】第6课—数据结构之栈
文章目录 1. 栈2. 栈的初始化和栈的销毁3. 入栈和出栈(压栈)4. 取栈顶元素并打印5. 栈的练习题5.1 有效的括号 1. 栈 栈:也是一种线性表,其数据结构与动态顺序表的数据结构类似栈分为栈顶和栈底,在栈中,插入…...