news 2026/5/14 21:01:33

《Java并发编程的艺术》| ConcurrentHashMap 在 JDK 1.7 与 1.8 的底层实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
《Java并发编程的艺术》| ConcurrentHashMap 在 JDK 1.7 与 1.8 的底层实现

摘要:本篇围绕 Java 并发容器核心,详细解析了 ConcurrentHashMap 在 JDK 1.7 和 JDK 1.8 版本中的实现原理与演进,并对比了其与 HashMap、Hashtable 的核心差异。

第6章 Java 并发容器

6.1 ConcurrentHashMap的实现原理与使用

6.1.1 为什么要使用ConcurrentHashMap

  • JDK1.7中的 HashMap 使用头插法插入元素,在多线程的环境下,扩容的时候有可能导致环形链表的出现,形成死循环。因此,JDK1.8使用尾插法插入元素,在扩容时会保持链表元素原本的顺序,不会出现环形链表问题。

  • 多线程同时执行 put 操作,如果计算出来的索引位置是相同的,那会造成前一个 key 被后一个 key 覆盖,从而导致元素的丢失。此问题在JDK 1.7和 JDK 1.8 中都存在。


常见的线程安全Map集合:

  • Hashtable是早期 Java 提供的线程安全的Map实现,它的实现方式与HashMap类似,但是在每个可能修改Hashtable状态的方法上加上synchronized关键字。

  • ConcurrentHashMap在 JDK 1.8 以前采用了分段锁等技术来提高并发性能。在ConcurrentHashMap中,将数据分成多个段(Segment),每个段都有自己的锁。在进行插入、删除等操作时,只需要获取相应段的锁,而不是整个Map的锁,这样可以允许多个线程同时访问不同的段,提高了并发访问的效率。在 JDK 1.8 以后是通过 volatile + CAS 或者 synchronized 来保证线程安全的。

6.1.2 ConcurrentHashMap 的结构

ConcurrentHashMap是由Segment和HashEntry组成。 Segment是一种可重入锁(ReentrantLock),在ConcurrentHashMap里扮演锁的角色;HashEntry则用于存储键值对数据。一个ConcurrentHashMap里包含一个Segment数组。Segment的结构和 HashMap类似,是一种数组和链表结构。一个Segment里包含一个HashEntry数组,每个HashEntry是一个链表结构的元素,每个Segment守护着一个HashEntry数组里的元素,当对HashEntry数组的数据进行修改时,必须首先获得与它对应的Segment锁。

这组图展示的是JDK 1.7 版本ConcurrentHashMap的核心设计,它是为了解决HashMap线程不安全和Hashtable效率低下的问题而诞生的。

分层结构与原理

  1. ConcurrentHashMap层(顶层容器)

    1. 内部维护一个Segment数组,相当于把整个哈希表拆分成了多个 "小 HashMap"。

    2. 这种 "分段锁" 设计,让不同 Segment 上的操作可以并发执行,大大提升了并发效率。

  2. Segment 层(分段锁实现)

    1. Segment本身继承了ReentrantLock,扮演锁的角色。

    2. 每个Segment守护着一个HashEntry数组,修改该数组中的元素前必须先获取对应的 Segment 锁。

    3. 它的结构和HashMap类似,也是数组 + 链表的结构。

  3. HashEntry 层(数据存储单元)

    1. 用于存储具体的键值对(Key-Value)。

    2. 每个HashEntry链表结构的节点,当发生哈希碰撞时,会以链表形式追加在对应位置

通俗来讲:

ConcurrentHashMap= 多个Segment组成的数组 | Segment = HashEntry数组 +ReentrantLock

Segment = HashEntry+ HashEntry ... | HashEntry(元素) = key + value + next 指针 +哈希值

ConcurrentHashMap怎么实现的? ⭐

JDK 1.7ConcurrentHashMap

JDK 1.7 中 ConcurrentHashMap 的底层结构是Segment[]数组(默认长度 16,不可扩容) + 每个 Segment 内部的HashEntry[]数组 + 链表;每个 Segment 继承自 ReentrantLock,持有独立的分段锁,相当于一个"小 HashMap"(HashEntry[]数组),各自管理一个 HashEntry [] 数组(存储该分段下的键值对);HashEntry 数组的每个元素是单向链表的头节点,哈希冲突的键值对以链表形式存储在同一个桶中。


JDK 1.8ConcurrentHashMap

在 JDK 1.7 中,ConcurrentHashMap 虽然是线程安全的,但因为它的底层实现是数组 + 链表的形式,所以在数据比较多的情况下访问是很慢的,因为要遍历整个链表,而 JDK 1.8 则使用了数组 + 链表/红黑树的方式优化了 ConcurrentHashMap 的实现,具体实现结构如下:

JDK 1.8 ConcurrentHashMap JDK 1.8 ConcurrentHashMap 主要通过 volatile + CAS 或者 synchronized 来实现的线程安全的。

添加元素时首先会判断容器是否为空:

如果为空则使用volatileCAS来初始化Node[]数组

如果容器不为空,定位元素位置并处理。

分两种情况处理:

  • 目标位置为空:直接通过CAS操作将新节点放入该位置(无需加锁,高效)。

  • 目标位置不为空(存在哈希冲突,已有链表或红黑树):

    • synchronized 锁定该位置的头节点(只锁链表 / 红黑树,而非数组,粒度更细)。

    • 遍历该位置的链表 / 红黑树,判断是否存在相同的键:若存在则替换值,否则新增节点。

    • 操作完成后,判断链表长度是否超过阈值,若超过则转为红黑树(优化查询性能)。

如果把上面的执行用一句话归纳的话,就相当于是ConcurrentHashMap通过对头结点加锁来保证线程安全的,锁的粒度相比 Segment 来说更小了,发生冲突和加锁的频率降低了,操作性能提高。

而且 JDK 1.8 使用的是红黑树优化了之前的固定链表,那么当数据量比较大的时候,查询性能也得到了很大的提升,从之前的 O(n) 优化到了 O(logn) 的时间复杂度。

ConcurrentHashMap用了悲观锁还是乐观锁?

悲观锁和乐观锁都有用到。

添加元素时首先会判断容器是否为空:

  • 如果为空则使用 volatile 加 CAS (乐观锁) 来初始化。

  • 如果容器不为空,则根据存储的元素计算该位置是否为空。

  • 如果根据存储的元素计算结果为空,则利用 CAS(乐观锁) 设置该节点;

  • 如果根据存储的元素计算结果不为空,则使用 synchronized(悲观锁) ,然后,遍历桶中的数据,并替换或新增节点到桶中,最后再判断是否需要转为红黑树,这样就能保证并发访问时的线程安全了。


恭喜你学习完本节内容!✿

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 7:04:58

dfs序+差分

lc2445hash预处理query&#xff0c;利用小的数不可能被大的数影响的单调性dfsclass Solution { public:int numberOfNodes(int n, vector<int>& queries) {map<int, int> cnt;for (auto& q: queries) cnt[q];function<int(int, int)> dfs [&] (…

作者头像 李华
网站建设 2026/5/1 6:20:49

【AI】AI 编程中的浏览器缓存陷阱:一次真实的踩坑经历

AI 编程中的浏览器缓存陷阱&#xff1a;一次真实的踩坑经历 问题背景 在使用 AI 辅助开发一个 RAG 知识库问答系统时&#xff0c;我遇到了一个让人困惑的问题&#xff1a; 搜索 “机器人料架取放料异常” 时&#xff0c;明明已经精确匹配到了正确的知识条目&#xff08;该条目没…

作者头像 李华
网站建设 2026/5/12 0:01:31

性能测试指标

记录下性能测试常用的几个指标&#xff0c;性能测试其实就是检查各项指标是否符合要求。 性能测试核心指标&#xff1a; 吞吐量 响应时间&#xff08;Rsponse Time&#xff09; 并发处理能力 资源占用能力 测试中的时间占比 40% ----- 性能测试分析 30% ----- 测试执行 …

作者头像 李华
网站建设 2026/5/14 7:37:05

中小厂找合作?这几款工具精准匹配上下游工厂资源

要说起中小制造企业的合作需求&#xff0c;那“寻找合适的合作伙伴”这件事&#xff0c;真的一直以来都挺让人觉得不轻松的&#xff0c;比如说&#xff0c;打算给自己家生产的产品寻觅配套的加工厂&#xff0c;结果在1688平台上&#xff0c;那些合作机会却经过贸易商一次又一次…

作者头像 李华
网站建设 2026/5/13 7:05:03

同步电机模型的MATLAB仿真

第2章同步电机基本原理 2.1理想同步电机 2.1.1理想同步电机假设 众所周知&#xff0c;由于转子结构的不同&#xff0c;同步电机可分为隐极机和凸极机两类。以下的研究对象像都是凸极机。 同步电机的主要特点是&#xff1a;定子有三相交流绕组&#xff0c;转子为直流励磁。 将电…

作者头像 李华
网站建设 2026/5/1 11:30:46

深度解析 GB/Z143-2025:养老服务标准化课程的技术框架与实践落地指南

在老龄化社会加速与数字化教育深度融合的背景下&#xff0c;养老服务领域的标准化、专业化人才缺口成为行业发展的核心瓶颈。近日&#xff0c;国家市场监督管理总局、国家标准化管理委员会正式发布 GB/Z143-2025《标准化教育课程建设指南 养老服务标准化》&#xff0c;为养老服…

作者头像 李华