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

ConcurrentHashMap 在Jdk 17 不同版本中的优化和改进

ConcurrentHashMap 是 Java 中的一个高性能线程安全的哈希表实现,随着 JDK 版本的迭代,其内部实现也经历了多次优化和改进。每个版本的改动针对不同的场景和需求进行了性能提升和问题修复。以下分别描述了 JDK 7、JDK 8 和 JDK 17 的主要设计和区别,并探讨了 JDK 17 的优化。

JDK 7 中的 ConcurrentHashMap

在 JDK 7 中,ConcurrentHashMap 使用的是 分段锁(Segment-based locking) 的设计。这种设计是通过将整个哈希表分成若干段(Segment),每段锁住部分桶来允许更高的并发度。

  • 设计特点
    • 哈希表被划分为多个 Segment,每个 Segment 都是一个独立的小型哈希表。
    • 针对每个 Segment 使用一个独立的锁,也就是说,一个线程修改某个 Segment 的数据不会影响其他线程对其他 Segment 的访问。
    • 每次触发写操作时,只需要对相应 Segment 加锁,而不是全表加锁。
  • 优缺点
    • 在高并发下性能表现较好,读操作无需锁定,只锁定写操作。
    • 并发粒度取决于 Segment 的数量(默认是 16),并发度有限。
    • 容量扩展时,每个 Segment 独立扩容,操作较复杂。

JDK 8 中的 ConcurrentHashMap

JDK 8 对 ConcurrentHashMap 的实现进行了大幅改进,采用了更加细粒度的锁和无锁化设计,摒弃了 JDK 7 中的分段锁结构,转而引入基于 CAS(Compare-And-Swap)的操作和红黑树优化。

  • 设计特点
    • 引入了 Node 数组结构,直接取代了 Segments,并采用了与 HashMap 类似的方式存储键值对。
    • CAS 操作 :通过 Unsafe 类的 CAS 指令操作底层数据,避免了锁的使用。
    • 红黑树优化 :当链表长度超过一定阈值(默认 8)时,将链表转换为红黑树,以避免链表过长时导致的查询性能下降。
    • 扩容时使用分批迁移机制(Rehashing ),由多个线程共同完成,降低扩容引起的性能问题。
    • compute()computeIfAbsent() 等操作进行了额外的同步控制,以支持复杂操作的线程安全性。
  • 改进效果
    • 移除了分段锁的限制,并发性提高。
    • 在链表出现太长时性能瓶颈显著降低。

JDK 17 中的 ConcurrentHashMap 的优化和改进

随着 JDK 的演进,ConcurrentHashMap 在 JDK 17 中进一步完善了设计,修复了一些潜在问题,同时在结构和算法上进行了优化,提升了并发性能和稳定性。

1. 性能优化
  • 更好的 CAS 重试逻辑
    • CAS 失败时的回退算法(退避机制)在 JDK 17 中进一步优化,以减少自旋导致的 CPU 消耗。
    • 对热点桶(比如在高并发下频繁访问的区域)进行了优化,使冲突降低。
  • 减少内存屏障的开销
    • 在兼容 JMM(Java 内存模型)的约束下,减少了不必要的内存屏障,改善了具体操作中的指令开销。
  • 改进批量操作的并发性能
    • 提升了 forEach, search, reduce 等聚合操作的并行度和效率,尤其是在高并发场景下对大数据集的处理能力。
2. 锁冲突优化
  • 在高并发场景中,当多个线程试图访问同一个节点时,JDK 17 中对节点锁的分配和抢占做了额外优化。例如,通过更智能的锁竞争算法来减少线程切换带来的上下文切换成本。
3. 红黑树相关修复
  • 修复了一些早期版本中红黑树实现的边缘问题(例如某些极端情况下可能导致的死循环问题)。
  • 优化了树结构在并发扩容和修改时的效率。
4. 线程挂起与唤醒机制改进
  • 在高并发写操作下,当线程需要等待其他线程完成某个关键部分(如扩容操作)时,采用了更加轻量化的线程挂起与唤醒机制,减少了不必要的上下文切换和线程阻塞。
5. 代码质量和一致性
  • 官方对代码进行了持续重构与优化,重点解决一些此前版本的边界条件、竞争状态(race condition)等潜在问题。
  • 保持与其他并发集合类(例如 ConcurrentSkipListMap)的操作逻辑风格一致。

JDK 7、8 和 17 中 ConcurrentHashMap 的主要差异总结

特性

JDK 7

JDK 8

JDK 17

锁机制

使用分段锁(Segment

基于 CAS 和 synchronized

改进的 CAS,减少锁竞争

数据结构

Segment

+ 链表

Node

+ 链表 + 红黑树

更优化的 Node

+ 链表 + 红黑树

扩容机制

每个 Segment

独立扩容

分批迁移完成扩容

改进的扩容效率,线程间协作更高效

高并发性能

易受分段数量限制

支持更高并发

性能进一步优化,高并发吞吐率提升

复杂操作支持(如计算)

较为有限

支持 compute

等复杂操作

改进 compute

等方法的性能


总结

  1. JDK 7 采用的是分段锁模型,适合中等并发的场景。
  2. JDK 8 引入了 CAS 和红黑树机制,极大提升了高并发场景下的性能,并摒弃了分段锁设计,成为近代 JVM 中并发集合的基础。
  3. JDK 17 在 JDK 8 的基础上进一步提升了并发性能,对锁冲突、CAS 回退、扩容机制等进行了优化,并修复了红黑树实现中的一些边缘问题,适用于更高并发的场景。

通常情况下,使用 JDK 17 提供的 ConcurrentHashMap 即可获得最好的性能和健壮性。


 

相关文章:

  • Python学习心得函数
  • 算法竞赛备赛——【背包DP】二维费用背包、分组背包
  • QEMU模拟运行FreeRTOS
  • Clash Nyanpasu设置VSCODE不走代理
  • 设计模式15:中介者模式
  • 使用html css js 来实现一个服装行业的企业站源码-静态网站模板
  • spring cloud gateway限流常见算法
  • 吸烟YOLO数据集,COCO格式
  • int* 和int的意思是不是一样
  • LLM 架构
  • 用deepseek学大模型08-cnn残差网络
  • 代码随想录刷题day24|(字符串篇)151.反转字符串中的单词
  • SECS/GEM300应用案例参考
  • 剑指 Offer II 023. 两个链表的第一个重合节点
  • 大模型应用怎么学习,在哪里实现开发:Dify、AnyThingLLM、LangFlow
  • Python .py文件打包成.exe可执行程序,带托盘图标的可执行文件
  • MySQL-事务
  • 【深度强化学习】置信域策略优化(TRPO)
  • Python的那些事第二十五篇:高效Web开发与扩展应用实践FastAPI
  • 【操作系统】操作系统概述
  • 中国社科院:网文市场超430亿元,作者破3000万人
  • 玉渊谭天丨中方为何此时同意与美方接触?出于这三个考虑
  • 1450亿元!财政部拟发行2025年中央金融机构注资特别国债(二期)
  • “爱鸟周”为何不能像FI和花展那样“市区联动”
  • 上海发布大风黄警:预计未来24小时内将出现8-10级大风
  • 夜读丨母亲的手擀面