当前位置: 首页 > news >正文

【Java】HashMap线程安全吗?

这篇是关于HashMap是否是线程安全的讲解,希望对大家有所帮助,也请大佬们多多指教,欢迎点赞、评论!!

HashMap不是线程安全的。

它的设计初衷是为了单线程环境下的高效哈希表操作,内部没有任何同步机制。
(如synchronized锁或volatile关键字),在多线程并发修改时会导致数据不一致、死循环等问题。

一、典型不安全场景:多线程并发扩容导致链表成环(JDK1.7及以前)

JDK1.7中,HashMap的底层结构是 数组+链表,当元素数量超过阈值(capacity*loadFactor)时会触发扩容(resize)
核心步骤是将就数组的元素迁移到新数组中(transfer方法)

多线程并发扩容时,可能导致链表节点的引用关系被破坏,形成环形链表,后续执行get操作时会陷入无限循环,导致CPU飙升。

场景复现步骤:

1、初始状态:

假设HashMap容量为2,负载因子为0.75,阈值为1.已有一个元素key=0(哈希后 落在索引为0),此时再插入元素会触发扩容(容量变为4)。

2.并发扩容:

  • 线程A和线程B同时执行put方法,均触发扩容,进入transfer方法。
  • 线程A先执行部分迁移,将旧数组索引0的链表(假设只有key=0)迁移到新数组,此时链表节点的next引用暂时被修改。
  • 线程B暂停后恢复执行,继续迁移时复用了线程A修改后的next引用,导致链表节点之间形成循环(比如:节点A的next引用指向节点B,节点B的next引用指向节点A)。

3.后果:

当后续线程执行get操作查询环形链表中的元素时,会陷入无限循环,无法退出。

二、其他线程不安全的场景:

1.数据覆盖:

多个线程同时执行put操作时,若两个线程计算出的哈希索引相同时,且同时判断该位置为空,会导致后执行的线程覆盖先执行线程插入的数据,造成数据丢失。

// 示例代码(多线程执行)
HashMap<String, Integer> map = new HashMap<>();// 线程1
new Thread(() -> map.put("key", 1)).start();
// 线程2
new Thread(() -> map.put("key", 2)).start();// 最终map中"key"的值可能是1或2,也可能出现异常(取决于执行时序)

2.size计数不准:

HashMap的size字段用于记录元素数量,多线程并发put/remove时,size++/size--操作不是原子性的(可能被打断),导致最终size与实际元素数量不符。

三、总结:

1.HashMap的线程不安全本质是缺乏同步机制,无法保证多线程操作的原子性、可见性和有序性,导致内部数据结构(数组、链表/红黑树)被破坏或数据不一致。

2.若需在多线程环境中使用哈希表,应该选择线程安全的替代类,如ConcurrentHashMap(JDK1.5+,高效并发)或、Collection.synchronizedMap(new HashMap<>())(全表加锁,效率较低)。

http://www.lryc.cn/news/610120.html

相关文章:

  • allegro建库--1
  • 【云馨AI-大模型】2025年8月第一周AI浪潮席卷全球:创新与政策双轮驱动
  • MLS平滑滤波
  • 洛谷 P3373 【模板】线段树 2- 普及+/提高
  • 《Python 实用项目与工具制作指南》· 3.1 实战·开发题目数据生成器
  • 思科 UCS Fabric Interconnect 和 UCS Manager 简介
  • 比起登天,孙宇晨更需要安稳着陆
  • C语言编程中常用的预定义宏
  • 浅谈 Python 中的 next() 函数 —— 迭代器的驱动引擎
  • 【深度学习新浪潮】近三年城市级数字孪生的研究进展一览
  • push/pop字节对齐使用场景
  • Next Terminal 实战:内网无密码安全登录
  • cocos2 场景跳转传参
  • 佰力博检测与您探讨介温谱和介电谱的区别?
  • 【实战】Dify从0到100进阶--中药科普助手(1)
  • 7.1、《软件工程》-软件生命周期-CMM-开发模型
  • 【2025/08/04】GitHub 今日热门项目
  • 【2025-08-04 Java学习小记】
  • Linux磁盘分区与挂载完全指南
  • Java基础学习(一):类名规范、返回值、注释、数据类型
  • 使用1panel将http升级至https的过程
  • javacc学习笔记 03、编译原理实践 - JavaCC解析表达式并生成抽象语法树
  • 深入解析线程同步中WaitForSingleObject的超时问题
  • 【Java基础知识 17】面向对象编程
  • Adobe Experience Manager (AEM) Assets|企业级数字资产管理平台(DAM)
  • javacc学习笔记 01、JavaCC本地安装与测试
  • TorchDynamo源码解析:从字节码拦截到性能优化的设计与实践
  • 厄米系统(Hermitian System)
  • Go 函数选项模式
  • 模型学习系列之考试