彻底讲透 JDK1.8 ConcurrentHashMap 线程安全原理
彻底讲透 JDK1.8 ConcurrentHashMap 线程安全原理全网最通俗图文完整版前言HashMap 线程不安全多线程并发 put 会出现数据覆盖、数据丢失JDK1.7 还会出现扩容死循环。为了解决并发安全问题JDK1.8 的 ConcurrentHashMap 抛弃了 JDK1.7 的 Segment 分段锁采用volatile CAS synchronized 并发扩容四大机制实现高性能线程安全。本文从零梳理底层结构、每一个机制的作用位置、适用场景、图文对照彻底搞懂 CHM 如何保证并发安全。一、底层数据结构总览图文JDK1.8 ConcurrentHashMap 底层结构数组 链表 红黑树1.1 普通链表桶结构无树化【volatile 数组引用】 transient volatile NodeK,V[] table ​ 数组堆内存结构 table[0] → null table[1] → Node1桶头节点 / synchronized 锁对象 ↓ next(volatile) Node2 ↓ next(volatile) Node3 ​核心规则数组中只有桶头 Node的引用存在 table 数组格子中链表后续 Node2、Node3不在数组中仅靠 Node.next 指针串联所有 Node 对象全部创建在堆内存1.2 红黑树桶结构树化后table[2] → TreeBin桶头、synchronized 锁对象继承 Node ├─ root → TreeNode红黑树根节点❗不是桶头 ├─ 挂载大量 TreeNode 左右子节点 └─ 内置读写锁提升并发读性能 ​重中之重90%人混淆树化后数组桶头不是 TreeNode而是TreeBinTreeNode 只是内部数据节点永远不会被锁synchronized 锁的是桶头 TreeBin 对象二、volatile 两层作用核心难点彻底拆解ConcurrentHashMap 有两套独立的 volatile 机制互不干扰这是最容易混淆的知识点。2.1 第一层volatile 修饰 table 数组引用transient volatile NodeK,V[] table;作用保证「数组引用切换」的可见性关键点纠正volatile不修饰数组内容、不修饰数组元素仅修饰table 这个变量保存数组堆地址数组一旦 new 出来自身堆地址永远不变volatile 只负责扩容/初始化时 table 新数组地址全局可见场景首次 put 初始化数组扩容结束切换新数组table nextTable保证所有线程立刻识别新数组不会继续读写旧数组避免数据错乱。2.2 第二层volatile 修饰 Node 内部字段static class NodeK,V { final int hash; final K key; volatile V val; // 值可见性 volatile NodeK,V next; // 指针可见性 }作用保证节点数据、链表结构的可见性val volatile一个线程修改 value其他线程立刻读到最新值next volatile线程追加新节点、修改链表指针其他遍历线程立刻感知链表变化核心价值支撑get() 无锁读取全程不加锁依靠 volatile 可见性拿到最新数据并发读性能极高。2.3 补充数组格子可见性Unsafe 兜底table 的 volatile 不管数组内部元素修改所以 JDK 底层通过三个 Unsafe 方法实现数组桶位的 volatile 读写tabAtvolatile 读桶头数据casTabAtCAS 无锁更新桶位setTabAtvolatile 写桶位数据三、CAS 无锁机制空桶写入专属3.1 核心定位CAS 是无锁乐观操作不是加锁适用唯一场景桶位为 null空桶// 如果当前桶为空CAS 尝试写入新节点 casTabAt(tab, i, null, new Node(hash, key, value, null));3.2 执行逻辑多线程同时写入同一个空桶CAS 比较内存值预期是 null 才写入只有一个线程成功其余线程自旋重试空桶场景无锁竞争性能极致避免了无脑加锁。四、synchronized 细粒度锁冲突场景核心保障当桶位已有数据链表/红黑树CAS 无法解决并发冲突启用 synchronized 互斥锁。4.1 锁对象核心规则全网最清晰总结链表桶锁「桶头普通 Node 节点」红黑树桶锁「桶头 TreeBin 对象」❌ 不锁链表所有节点、❌ 不锁 TreeNode、❌ 不锁数组4.2 如何实现锁住整条桶数据并不是语法上锁了整条链表/红黑树而是并发约定所有线程修改同一个桶的数据必须先竞争桶头锁同一时刻只有一个线程能修改该桶从而保证整条链表/红黑树的线程安全。4.3 锁粒度优势不同桶互不阻塞支持最大并发废弃 JDK1.7 笨重的 Segment 分段锁JDK1.8 对 synchronized 做了大量优化偏向锁/轻量级锁性能远超 ReentrantLock五、并发扩容机制兜底线程安全CHM 扩容不会阻塞所有线程支持多线程协助扩容是高并发核心亮点。5.1 核心流程达到扩容阈值新建 nextTable 新数组原桶正在迁移时标记为ForwardingNode其他线程写入时发现桶是 ForwardingNode先协助扩容迁移完成再写入全部迁移完毕执行table nextTablevolatile 全局可见彻底解决了 HashMap 扩容死循环、数据丢失问题。六、完整 put 执行流程串联所有机制判断数组是否未初始化CAS 初始化数组volatile 保证数组引用可见计算 hash 定位桶下标通过 tabAt volatile 读获取最新桶头桶为空CAS 无锁写入新节点桶正在扩容协助扩容后再写入桶已有数据synchronized 锁桶头链表遍历覆盖/追加节点依靠 node val/next volatile 保证可见性链表长度≥8 且数组≥64转为红黑树更新元素数量判断是否触发扩容七、最终总结可直接背诵、发博客收尾JDK1.8 ConcurrentHashMap 依靠三层可见性 无锁CAS 细粒度锁 并发扩容全方位保证线程安全volatile 两层可见性table 数组引用保证扩容切换全局可见Node 的 val、next 保证节点数据和链表结构实时可见支撑无锁读。CAS 无锁写入空桶场景乐观写入无锁高并发避免多余锁竞争。synchronized 细粒度互斥冲突场景锁桶头Node/TreeBin仅阻塞同桶线程最大化并发性能。并发扩容机制多线程协助迁移扩容不阻塞读写彻底解决并发扩容数据异常问题。相比 JDK1.7 分段锁锁粒度更细、并发度更高、读写性能更优是 Java 高并发场景下的标准键值存储方案。注部分内容可能由 AI 生成

相关新闻

某车EPB电子驻车系统

某车EPB电子驻车系统

1.传统机械驻车 为了便于了解电子驻车原理,首先需要了解一下传统机械驻车系统,它由驻车制动手阀、挂车手阀、继动阀、挂车控制阀、复合制动气室等部件组成。系统功能包括驻车制动、应急制动、挂车制动三个方面。 ①驻车制动控制: 挂车制动控制…

2026/9/15 3:43:20 阅读更多 →
WAF防护原理与轻量绕过思路

WAF防护原理与轻量绕过思路

09-WAF防护原理与轻量绕过思路合法边界声明:本篇讨论的绕过思路仅用于两个场景——一是在自建靶场/授权渗透测试中评估防护设备的真实效果,二是帮助防守方理解绕过手法从而完善规则。对未授权目标实施任何绕过尝试均属违法行为。WAF 绕过是"矛与盾&…

2026/9/13 22:51:58 阅读更多 →
30分钟从零烧录第一块板:Arduino-ESP32 3.x 核心上手全解

30分钟从零烧录第一块板:Arduino-ESP32 3.x 核心上手全解

30分钟从零烧录第一块板:Arduino-ESP32 3.x 核心上手全解 【免费下载链接】arduino-esp32 Arduino core for the ESP32 family of SoCs 项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32 你刚把 ESP32 开发板插上电脑,Arduino ID…

2026/9/13 22:51:58 阅读更多 →

最新新闻

Unity战棋游戏源码解析:网格、寻路与回合状态机实战

Unity战棋游戏源码解析:网格、寻路与回合状态机实战

简介:基于Unity引擎的战棋游戏(SSRPG)完整工程源码,面向Unity初级、中级开发者及对回合制战棋玩法感兴趣的爱好者,帮助理解从零搭建策略游戏的核心框架。项目实现随机地图生成(随机游走与细胞洞穴算法&…

2026/9/15 3:53:07 阅读更多 →
ScyllaDB Nodetool ring 命令详解:令牌环信息查询与分区分布诊断

ScyllaDB Nodetool ring 命令详解:令牌环信息查询与分区分布诊断

ScyllaDB Nodetool ring 命令详解:令牌环信息查询与分区分布诊断 【免费下载链接】scylladb NoSQL data store using the Seastar framework, compatible with Apache Cassandra and Amazon DynamoDB 项目地址: https://gitcode.com/GitHub_Trending/sc/scylladb …

2026/9/15 3:53:07 阅读更多 →
Linux嵌入式驱动开发:设备树、I2C与CAN实战调试全链路

Linux嵌入式驱动开发:设备树、I2C与CAN实战调试全链路

1. 这不是教科书里的“Hello World”,而是嵌入式产线现场的真实驱动开发路径你手头刚拿到一块瑞芯微RK3568的开发板,上面焊着一颗SSD1306 OLED屏、一个I2C温湿度传感器、还有一路CAN总线连接着电机控制器——老板说:“下周要联调,…

2026/9/15 3:53:07 阅读更多 →
Python飞机大战课程设计:源码解析与pygame游戏开发实战

Python飞机大战课程设计:源码解析与pygame游戏开发实战

简介:飞机大战课程设计源码包基于 Python 与 Pygame 实现,面向需要完成课程设计、大作业或希望练手 Python 游戏开发的初学者,也适合对现有框架做二次开发的进阶用户。压缩包仅 1.68MB,共收录 69 个文件,包含 15 个游戏…

2026/9/15 3:53:07 阅读更多 →
RK3568设备树与I2C/CAN驱动协同开发实战

RK3568设备树与I2C/CAN驱动协同开发实战

1. 这不是教科书,是我在RK3568项目里焊过板子、改过dts、抓过I2C波形、调通CAN节点后写下的实操笔记“Linux设备驱动开发:从内核模块到设备树、I2C/CAN的系统路径”——这个标题看着像课程大纲,但实际是嵌入式一线工程师每天面对的真实工作流…

2026/9/15 3:53:07 阅读更多 →
SAM在工业检测中的工程化落地:从零样本分割到产线部署

SAM在工业检测中的工程化落地:从零样本分割到产线部署

1. 这不是又一个“炫技模型”,而是工业检测流水线上的新工人最近在东莞一家做PCB板自动质检的工厂蹲了两周,亲眼看着产线老师傅把一台刚部署好的视觉检测设备调得越来越稳。他没说太多技术词,就指着屏幕上被精准框出来的微小焊点虚焊区域说&a…

2026/9/15 3:52:07 阅读更多 →

日新闻

Java高级技术:从语言特性到性能优化全解析

Java高级技术:从语言特性到性能优化全解析

1. Java高级技术概述Java作为一门成熟的编程语言,经过二十多年的发展已经形成了完整的生态系统。在企业级应用开发、大数据处理、移动开发等领域,Java都占据着重要地位。掌握Java高级技术不仅意味着能够编写更高效的代码,更代表着开发者能够解…

2026/9/15 0:00:23 阅读更多 →
C#与Halcon结合的工业视觉处理实战指南

C#与Halcon结合的工业视觉处理实战指南

1. 项目概述:C#与Halcon强强联合的视觉处理利器这个基于C#和Halcon的视觉处理Demo项目,是我在工业质检领域摸爬滚打多年后提炼出的实战精华。它完美融合了C#的界面开发优势与Halcon强大的图像处理能力,就像给视觉工程师配上了一把瑞士军刀。项…

2026/9/15 0:00:23 阅读更多 →
32路工业串口服务器的硬核选型指南:确定性、鲁棒性与协议下沉

32路工业串口服务器的硬核选型指南:确定性、鲁棒性与协议下沉

1. 为什么“32路复合型”不是营销话术,而是工业现场真实痛点的硬解你有没有遇到过这样的场景:在某大型能源站的PLC机柜里,十几台不同年代、不同品牌的温控仪、电表、气体分析仪、阀门控制器,全靠RS-485总线挂在一根线上&#xff0…

2026/9/15 0:00:23 阅读更多 →

周新闻

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验 【免费下载链接】ai The AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and ag…

2026/9/14 5:45:49 阅读更多 →
Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化 【免费下载链接】refine A React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility. 项目地址: https://gitcode.com/GitH…

2026/9/15 1:32:25 阅读更多 →
Flutter应用改名全指南:从Android到iOS的配置与工具实践

Flutter应用改名全指南:从Android到iOS的配置与工具实践

刚接一个外包项目时,甲方要求把工程里临时用的应用名改成正式产品名。我本来觉得“改名”这种小事,打开配置文件改一行不就完了?结果真动手才发现,Flutter项目里“应用名称”根本不是一处配置,而是一整套散落在 Androi…

2026/9/15 1:32:21 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/14 17:35:10 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/14 16:59:29 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/14 5:45:14 阅读更多 →