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

深度拆解 JDK1.8 ConcurrentHashMap 核心方法:从 put 到扩容,彻底吃透并发神器

在 Java 高并发编程中ConcurrentHashMap是线程安全 Map 的绝对首选而 JDK1.8 版本对它的重构堪称并发设计的巅峰之作 —— 彻底抛弃分段锁用CAS 桶级 synchronized实现极致细粒度并发搭配多线程协同扩容、链表红黑树转换、高性能计数机制解决了前辈版本的所有性能痛点。这篇博客我们不聊历史演进只聚焦 JDK1.8 ConcurrentHashMap 最核心的方法逐行拆解原理、流程、亮点把并发底层逻辑讲得明明白白。前言核心设计总览JDK1.8 ConcurrentHashMap 的底层是Node 数组 链表 红黑树核心并发原则读操作全程无锁靠 volatile 保证可见性写操作能无锁则无锁需加锁则最小粒度加锁扩容不阻塞业务线程多线程协同提速计数分散无竞争高并发下性能稳定。下文将拆解put 写操作、get 读操作、transfer 扩容、addCount 计数四大核心方法这是 ConcurrentHashMap 的灵魂。一、核心写操作putVal 方法最核心我们平时调用的map.put(key,value)底层全部交给final V putVal(K key, V value, boolean onlyIfAbsent)执行这是 ConcurrentHashMap 并发能力的集中体现。1.1 核心亮点必须牢记CAS 无锁插入目标桶为空时直接 CAS 原子插入不加锁桶级 synchronized 锁只锁当前哈希桶的头节点不同桶完全并行协助扩容遇到扩容标记节点主动帮忙迁移数据不等待链表树化长度超限自动转红黑树避免长链表查询卡顿。1.2 完整执行流程图文级拆解final V putVal(K key, V value, boolean onlyIfAbsent) { // 严格禁止key/value为null区别于HashMap if (key null || value null) throw new NullPointerException(); // 哈希扰动降低哈希冲突概率 int hash spread(key.hashCode()); int binCount 0; // 自旋保证操作一定成功 for (NodeK,V[] tab table;;) { NodeK,V f; int n, i, fh; // -------------- 步骤1数组未初始化先初始化 -------------- if (tab null || (n tab.length) 0) tab initTable(); // -------------- 步骤2目标桶为空CAS无锁插入 -------------- else if ((f tabAt(tab, i (n - 1) hash)) null) { // 原子更新无锁、无阻塞成功直接退出循环 if (casTabAt(tab, i, null, new NodeK,V(hash, key, value, null))) break; } // -------------- 步骤3发现扩容标记协助扩容 -------------- // fh MOVED(-1)说明当前桶正在迁移 else if ((fh f.hash) MOVED) tab helpTransfer(tab, f); // -------------- 步骤4桶有数据加锁写入 -------------- else { V oldVal null; // 关键只锁定当前桶的头节点锁粒度最小 synchronized (f) { // 双重检查防止加锁前头节点被其他线程修改 if (tabAt(tab, i) f) { // -------- 子逻辑1链表结构遍历插入/更新 -------- if (fh 0) { binCount 1; for (NodeK,V e f;; binCount) { K ek; // key已存在更新value if (e.hash hash ((ek e.key) key || key.equals(ek))) { oldVal e.val; if (!onlyIfAbsent) e.val value; break; } NodeK,V pred e; // 尾插法新增节点 if ((e e.next) null) { pred.next new NodeK,V(hash, key, value, null); break; } } } // -------- 子逻辑2红黑树结构树节点插入 -------- else if (f instanceof TreeBin) { NodeK,V p; binCount 2; if ((p ((TreeBinK,V)f).putTreeVal(hash, key, value)) ! null) { oldVal p.val; if (!onlyIfAbsent) p.val value; } } } } } // -------------- 步骤5链表过长树化 -------------- if (binCount ! 0) { // 长度≥8尝试树化数组长度64时优先扩容不树化 if (binCount TREEIFY_THRESHOLD) treeifyBin(tab, i); if (oldVal ! null) return oldVal; break; } } // -------------- 步骤6计数判断是否需要扩容 -------------- addCount(1L, binCount); return null; }1.3 关键细节解释自旋死循环保证 CAS 失败 / 并发冲突时能重试直到成功tabAt/casTabAt使用Unsafe原子操作读写数组保证线程可见synchronized(f)只锁头节点不同桶之间完全无竞争并发度 数组长度树化条件链表长度≥8且数组长度≥64否则优先扩容分散数据。二、核心读操作get 方法全程无锁ConcurrentHashMap 的高性能一半来自无锁读。2.1 执行流程public V get(Object key) { NodeK,V[] tab; NodeK,V e, p; int n, eh; K ek; int h spread(key.hashCode()); // 1. 定位桶位置 if ((tab table) ! null (n tab.length) 0 (e tabAt(tab, (n - 1) h)) ! null) { // 2. 头节点匹配直接返回 if ((eh e.hash) h) { if ((ek e.key) key || (ek ! null key.equals(ek))) return e.val; } // 3. 扩容节点/红黑树查询 else if (eh 0) return (p e.find(h, key)) ! null ? p.val : null; // 4. 遍历链表查询 while ((e e.next) ! null) { if (e.hash h ((ek e.key) key || (ek ! null key.equals(ek)))) return e.val; } } return null; }2.2 为什么无锁还能线程安全Node[] table、Node.val、Node.next全部用volatile修饰volatile 禁止指令重排保证写线程的修改对读线程立即可见读操作只读取、不修改天然无竞争不需要加锁。无锁读 超高并发 零锁开销这是 ConcurrentHashMap 碾压 Hashtable 的关键。三、核心扩容机制transfer 方法多线程协同JDK1.8 最惊艳的设计就是无阻塞、多线程协同扩容彻底解决了 JDK1.7 单段扩容卡顿的问题。3.1 扩容核心标记sizeCtlsizeCtl 0扩容阈值容量 × 负载因子sizeCtl -1正在初始化sizeCtl -1有N-1个线程正在协同扩容3.2 扩容完整流程元素总数达到阈值触发扩容新建 2 倍容量的nextTable多线程分段迁移桶每个线程认领一段桶互不干扰迁移完成的桶放置ForwardingNodehash-1标记其他线程写数据时遇到标记会协助扩容不阻塞全部迁移完成table指向新数组更新阈值。3.3 核心优势扩容期间不阻塞读写多线程加速并发越高扩容越快迁移过程安全无数据丢失。四、核心计数机制addCount size ()高并发下size()如果加锁统计会极慢JDK1.8 采用分段计数设计对标LongAdder。4.1 双计数结构baseCount基础计数器低并发直接更新CounterCell[]分段单元格高并发冲突时分散计数4.2 执行逻辑无竞争直接CAS更新baseCount有竞争使用CounterCell每个线程更新自己的单元格无竞争size()求和baseCount 所有CounterCell弱一致性不加锁性能优先。4.3 为什么是弱一致统计过程中可能有新写入数值不是绝对精确高并发场景下性能远比重度精确更重要业务需要精确计数时需自行加锁。五、JDK1.8 ConcurrentHashMap 优缺点总结优点✅锁粒度最小桶级锁并发度拉满✅无锁优化空桶 CAS 插入零锁开销✅红黑树解决长链表 O (n) 查询问题✅多线程扩容扩容不阻塞速度极快✅无锁读读性能无限接近 HashMap✅内存高效无 Segment 分段节省内存✅高性能计数高并发下无竞争缺点❌ 实现极其复杂CAS、扩容、红黑树❌ 同一桶竞争仍会阻塞❌ size () 为弱一致性不保证绝对精确六、JDK17 优化补充无结构变更JDK17 是 LTS 版本核心设计完全保留 JDK1.8只做底层优化低延迟 GCZGC/Shenandoah大幅降低 GC 停顿并发更稳定CounterCell 伪共享优化提升计数性能Graal 编译器优化锁、CAS 执行更快红黑树、volatile 读写细节微调。实测JDK17 比 JDK8 吞吐量提升 10%~15%大内存场景优势更明显。七、面试 开发必背核心点put 先 CAS 后加锁只锁头节点get 全程无锁靠 volatile 保证可见性扩容多线程协同遇到标记会协助迁移链表≥8 转红黑树且数组必须≥64不允许 key/value 为 nullsize () 弱一致高性能优先JDK1.8 之后不再用分段锁。结尾ConcurrentHashMap JDK1.8 版本是 Java 并发编程的教科书级实现用最小的锁、最大的无锁、最聪明的扩容、最分散的计数实现了线程安全与高性能的完美平衡。理解它的四大核心方法put、get、transfer、addCount你就真正吃透了 Java 高并发 Map 的底层精髓无论是面试还是工程开发都能游刃有余。后续 Java 版本只会持续做性能优化JDK1.8 这套核心架构会长期成为标准。总结这篇博客完整拆解了JDK1.8 ConcurrentHashMap 四大核心方法putValCAS 无锁插入 桶级锁 协助扩容 链表树化get全程无锁volatile 保证可见性transfer多线程协同扩容无阻塞addCountbaseCountCounterCells 高性能计数同时明确了 JDK17 仅做优化、不改动核心设计帮你一次性掌握企业级最常用的并发 Map 原理。

相关文章:

深度拆解 JDK1.8 ConcurrentHashMap 核心方法:从 put 到扩容,彻底吃透并发神器

在 Java 高并发编程中,ConcurrentHashMap是线程安全 Map 的绝对首选,而 JDK1.8 版本对它的重构堪称并发设计的巅峰之作 —— 彻底抛弃分段锁,用CAS 桶级 synchronized实现极致细粒度并发,搭配多线程协同扩容、链表红黑树转换、高…...

毕业季、返修季、投稿季:SCI论文润色,到底能不能提高接收率?

“SCI论文如果先润色,再投稿,是不是更容易被接收?”这个问题,真的每年到了这个时间点都会高频出现。尤其是3月底到4月初,很多同学刚从基金申请、毕业论文、返修修改的高压节奏里缓过来,马上又进入下一轮“赶…...

KITTI数据集实战指南:从下载到3D目标检测全流程解析(附避坑技巧)

KITTI数据集实战指南:从下载到3D目标检测全流程解析(附避坑技巧) 1. 为什么选择KITTI数据集? 在计算机视觉和自动驾驶研究领域,数据是算法进步的基石。KITTI数据集自2012年发布以来,已成为全球最具影响力的…...

UML(Unified Modeling Language,统一建模语言)是一种标准化的可视化建模语言,广泛用于软件系统的需求分析

UML(Unified Modeling Language,统一建模语言)是一种标准化的可视化建模语言,广泛用于软件系统的需求分析、设计与文档化。你列出的是UML 2.x 中最常用的六种结构与行为图,分别属于两大类: ✅ 结构图&#…...

react二次封装

先在src下创建一个utils文件一次封装下载npm install axios在utils文件创建个request.jsimport axios from axios;// 创建axios实例 const instance axios.create({timeout: 10000,headers: {Content-Type: application/json},baseURL: https://zzgoodqc.cn/ });// 请求拦截器…...

3个关键技巧彻底解决Photoshop WebP格式兼容性问题

3个关键技巧彻底解决Photoshop WebP格式兼容性问题 【免费下载链接】WebPShop Photoshop plug-in for opening and saving WebP images 项目地址: https://gitcode.com/gh_mirrors/we/WebPShop 在当今Web开发与设计领域,WebP格式已成为图像优化的黄金标准&am…...

用2万小时人类视频预训练机器人,一场豪赌还是必经之路?

先说结论核心验证了“人类数据缩放定律”:在灵巧操作任务上,模型性能随人类预训练数据量对数线性增长,为数据策略提供了可预测的依据。成功的关键在于“两阶段迁移”设计:用大规模、廉价但“嘈杂”的人类数据奠基通用结构&#xf…...

通义千问多模态检索系统:图文视频混合输入全解析

通义千问多模态检索系统:图文视频混合输入全解析 1. 多模态检索的行业痛点与解决方案 在信息爆炸的时代,传统文本检索系统面临三大核心挑战: 跨模态匹配失效:用户用文字描述"红色跑车在沙漠驰骋",系统却返…...

GPEN图像修复新手入门:界面介绍与功能详解

GPEN图像修复新手入门:界面介绍与功能详解 1. 认识GPEN图像修复工具 你是否遇到过这样的情况:翻出老照片想分享给亲友,却发现照片已经泛黄、模糊甚至出现划痕?GPEN图像修复工具就是为解决这些问题而生的专业解决方案。这个由科哥…...

英雄联盟游戏助手:5大功能全面解析,打造你的专属游戏体验

英雄联盟游戏助手:5大功能全面解析,打造你的专属游戏体验 【免费下载链接】League-Toolkit 兴趣使然的、简单易用的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit …...

利用快马平台快速生成javascript交互原型:以动态待办列表为例

利用快马平台快速生成JavaScript交互原型:以动态待办列表为例 最近在尝试快速验证一个待办事项应用的交互设计,发现用传统方式从零开始写代码太耗时了。正好试用了InsCode(快马)平台,只需要描述功能需求,就能自动生成可运行的Jav…...

LH6828@ACP#6828#484 USB3.1 全通道 4:1/1:4 10Gbps 多路复用 / 解复用器 产品规格、应用分享及CH484规格对比

LH6828 是一款高性能全通道高速双向无源开关,专为 USB Type-C 生态系统设计,深度适配 USB3.1 Gen1(5Gbps)/Gen2(10Gbps)超高速传输协议,支持 4 组设备全通道信号的 4:1/1:4 双向切换&#xff0c…...

注CO2驱替煤层气THM耦合模型与自定义PDE耦合固体力学

注co2驱替煤层气THM耦合模型 自定义pde耦合固体力学今天,我来分享一下关于CO2驱替煤层气的THM(热-水-力学)耦合模型的构建过程。这个模型听起来有点复杂,但其实拆开来理解,每一步都还挺有意思的。尤其是其中涉及的自定…...

大模型Transformer架构学习

基础知识: 损失函数:梯度下降单次训练过程过拟合数据增强:增加训练数据,对原始数据加噪,翻转,旋转 正则化:防止该函数过分变化,让损失函数加上该参数,调整损失函数时会抑…...

告别传统BPMN:wflow工作流设计器如何让普通员工5分钟搭建审批流程?

告别传统BPMN:wflow工作流设计器如何让普通员工5分钟搭建审批流程? 【免费下载链接】wflow workflow 工作流设计器,企业OA流程设计。表单流程设计界面操作超级简单!!普通用户也能分分钟上手,不需要专业知识…...

OpenClaw人人养虾:网关架构

本文档描述 Gateway(网关)的内部架构设计,帮助你理解各组件之间的协作关系。 架构总览 ┌──────────────────────────────────────────────────────────┐ │ …...

给视觉新手的保姆级教程:用Python+OpenCV玩转四步相移结构光(附代码)

零基础实战:用PythonOpenCV实现四步相移结构光三维重建 在计算机视觉领域,结构光三维重建技术因其高精度和非接触特性,被广泛应用于工业检测、逆向工程和医疗成像。对于刚接触这一领域的新手来说,最困扰的往往不是理解原理&#x…...

把 SAP ABAP CDS View Code Mapping 讲透:从 SEGW 映射到 SADL 运行时的关键机制与项目实践

很多 ABAP 开发者在第一次接触 CDS View Code Mapping 时,容易把它理解成一次普通的字段映射操作:左边是 CDS 字段,右边是 OData 属性,拖一拖、连一连,事情就结束了。真正进入项目以后,大家才会发现,这个动作背后牵动的是 SAP Gateway、SADL、DPC 运行时、关联导航,以及…...

[小红书AI自动化教程]凌晨2点我在睡觉,AI偷偷发了篇小红书爆款:醒来99+点赞,人类社媒苦役终结?

我把小红书交给 OpenClaw,它开始自己干活了 凌晨两点,我在睡觉,它却偷偷发了一篇爆款。 醒来点赞99,评论全是“姐妹求链接”。这不是科幻。去年我还为追热点熬夜秃头,如今一句“今天发什么”,AI 就能完成选…...

用NoneBot2给Lagrange机器人加buff:5个提升效率的插件开发技巧

用NoneBot2给Lagrange机器人加buff:5个提升效率的插件开发技巧 在智能对话机器人领域,NoneBot2与Lagrange的组合已经成为QQ生态中高效开发的黄金搭档。但当你已经掌握了基础功能开发后,如何让机器人更智能、更稳定、更能应对复杂场景&#xf…...

英雄联盟智能助手完全指南:3分钟掌握LCU API自动化工具

英雄联盟智能助手完全指南:3分钟掌握LCU API自动化工具 【免费下载链接】League-Toolkit 兴趣使然的、简单易用的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 还在为英雄联盟…...

基于springboot框架个性化旅游线路推荐系统 景区门票 酒店 预订88u7sgf 有论文-idea maven vue

目录系统架构设计技术选型与工具数据库设计核心功能实现论文研究要点开发计划安排项目技术支持源码获取详细视频演示 :文章底部获取博主联系方式!同行可合作系统架构设计 采用前后端分离架构,后端基于SpringBoot框架,前端使用Vue…...

Vue项目实战:集成Cesium加载天地图与高德地图的完整指南

1. 环境准备与项目初始化 在开始集成Cesium之前,我们需要先搭建好Vue的开发环境。这里我推荐使用Vue 3的组合式API,因为它的模块化特性与Cesium的集成更加契合。不过Vue 2的用户也不用担心,大部分代码都是兼容的。 首先创建一个新的Vue项目…...

避坑指南:运行YooAsset 2.3.9官方Demo时,你可能会遇到的Sprite白块和退出报错

避坑指南:YooAsset 2.3.9官方Demo运行时的Sprite白块与退出报错深度解析 当Unity开发者初次接触YooAsset资源管理系统时,官方Demo往往是快速上手的最佳途径。然而在YooAsset 2.3.9版本的示例项目中,不少开发者反馈遇到了两个典型问题&#x…...

ARM A53上跑通1080P实时EIS防抖?手把手教你优化特征点与透视变换(附代码思路)

ARM A53实战:1080P实时EIS防抖的7个关键优化策略 当行车记录仪的镜头在颠簸路面剧烈晃动,或是运动相机在冲浪时被海浪拍打,画面稳定性的价值就凸显出来。传统光学防抖受限于物理结构,而电子防抖(EIS)通过算法补偿成为嵌入式设备的…...

Word制表位全攻略:从菜鸟到高手,5分钟搞定专业文档排版

Word制表位全攻略:从菜鸟到高手,5分钟搞定专业文档排版 你是否曾经为了对齐文档中的文字而疯狂敲击空格键?或是花费大量时间调整表格边框却依然无法让数字完美对齐?这些困扰其实只需要掌握一个Word中的隐藏神器——制表位&#x…...

别再为长文档发愁了!用DeepSeek-OCR + 单块A100,5步搞定古籍/财报批量识别

单块A100实战指南:用DeepSeek-OCR高效处理古籍与财报的5个关键步骤 当某省级图书馆需要数字化10万页明清古籍时,技术团队发现传统OCR方案需要3个月才能完成,而采用DeepSeek-OCR配合单块A100的方案,仅用11天就交付了准确率92%的数…...

BERT文本分割-中文模型企业应用:内容平台文档结构化

BERT文本分割-中文模型企业应用:内容平台文档结构化 1. 引言:为什么需要文本分割技术 在日常工作中,我们经常会遇到这样的情况:会议记录、访谈稿、讲座内容等长篇口语文字材料缺乏段落结构,阅读起来十分困难。这些由…...

深度解析跨平台音频驱动:FlexASIO实战配置指南

深度解析跨平台音频驱动:FlexASIO实战配置指南 【免费下载链接】FlexASIO A flexible universal ASIO driver that uses the PortAudio sound I/O library. Supports WASAPI (shared and exclusive), KS, DirectSound and MME. 项目地址: https://gitcode.com/gh_…...

保姆级教程:在Win10上用Docker Desktop搞定Dify,再接入本地DeepSeek模型

保姆级教程:在Win10上用Docker Desktop搞定Dify,再接入本地DeepSeek模型 如果你是一位Windows 10用户,同时对AI应用开发充满兴趣,那么这篇教程就是为你量身定制的。我们将一步步带你完成Dify平台的部署,并将其与本地运…...