深度解析 ConcurrentHashMap:从源码到实战

JDK 1.8 桶级锁 + CAS,抛弃 Segment,直接 synchronized 锁单个首节点,冲突时才加锁;扩容时多线程协同迁移,CPU 利用率拉满。

一、前言

线程安全

并发度

备注

HashMap

×

——

最快,但多线程下 CPU 100% 死循环曾坑哭无数码农

Hashtable

全表一把锁,基本等同于串行

Collections.synchronizedMap

同上,只是包装器

ConcurrentHashMap

极高

分段/桶级锁 + CAS,读写可并行,扩容亦并发

结论:并发场景下,CHM 是唯一“能扛流量又能打”的哈希表实现。

二、数据结构演进史

  1. JDK 1.5 分段锁(Segment)16 个可重入锁,理论并发度 16。
  2. JDK 1.8 桶级锁 + CAS抛弃 Segment,直接 synchronized 锁单个首节点,冲突时才加锁;扩容时多线程协同迁移,CPU 利用率拉满。

三、JDK 1.8 核心成员变量速览

// 位标识
staticfinalint MOVED     = -1; // ForwardingNode
staticfinalint TREEBIN   = -2; // 红黑树根
staticfinalint RESERVED  = -3; // computeIfAbsent 占位

transientvolatile Node<K,V>[] table;      // 主哈希桶
privatetransientvolatile Node<K,V>[] nextTable; // 扩容目标数组
privatetransientvolatilelong baseCount; // 无冲突时直接累加
privatetransientvolatileint sizeCtl;    // 控制标识:负数=正在扩容/-1=初始化/n=扩容阈值

四、put 流程(含并发控制)

  1. 空表首次初始化通过 CAS 将 sizeCtl 从 0 改为 -1,单线程建表,其余线程 Thread.yield() 自旋等待。
  2. 计算哈希spread(key.hashCode()) 再散列,减少哈希碰撞。
  3. 定位桶(n - 1) & hash,与 HashMap 一致。
  4. 桶为空CAS 插入新节点,失败则自旋。
  5. 桶非空首节点 hash == MOVED → 帮忙扩容 (helpTransfer)。否则 synchronized 锁定首节点,再按链表/红黑树逻辑插入或更新。
  6. 计数 + 检查扩容addCount(1L, binCount),若超过 sizeCtl 则触发 transfer。

五、get 流程——全程无锁

  1. 计算哈希定位桶。
  2. 首节点匹配直接返回。
  3. 红黑树则按树查找;链表顺序遍历。
  4. 遇到 ForwardingNode 去 nextTable 重新查找。

可见性保障:Node.val 用 volatile 修饰;扩容时旧表只读,新表发布前通过 Unsafe 的 volatile 写保证。

六、扩容(transfer)——多线程协同搬运

  1. 步长 stride根据 CPU 核数计算每次迁移的桶数(最小 16),减少竞争。
  2. 全局进度索引 transferIndex从高位往低位分配任务包,CAS 抢占。
  3. 搬运算法对单个桶加 synchronized,构建新链表/树,插入到新表,旧桶头插 ForwardingNode 占位。
  4. 帮助扩容插入时发现 MOVED,当前线程领取stride步任务,加快迁移。

七、线程安全计数器

  • baseCount:无竞争时直接累加。
  • **CounterCell[]**:高并发时分散到数组,类似 LongAdder,最终 sumCount() 汇总。

八、红黑树与链表互转阈值

方向

阈值

说明

链表 → 树

8

且桶总数 ≥ 64,否则优先扩容

树 → 链表

6

删除节点后检查

九、实战踩坑指南

  1. 复合操作非原子
if (!map.containsKey(k)) map.put(k, v); // 仍有竞态

    正确姿势:putIfAbsent(k, v) 或 computeIfAbsent。

    1. 遍历一致性Iterator 弱一致性:创建后其他线程增删改不抛 ConcurrentModificationException,但未必可见。
    2. 自定义对象作为 key必须保证不可变且正确实现 hashCode/equals,否则扩容前后定位桶不一致导致“幽灵丢失”。
    3. 批量操作forEach、search、reduce 支持并行化,可指定 parallelismThreshold,在大数据量场景比串行循环快 2~3 倍。

    十、性能压测对比(1.8 vs 1.7 vs Hashtable)

    测试场景:32 线程,各执行 1 千万次 put。

    实现

    耗时 (ms)

    吞吐量 (ops/us)

    Hashtable

    28 000

    0.36

    CHM 1.7

    4 100

    2.44

    CHM 1.8

    2 300

    4.35

    结论:1.8 桶级锁 + 协同扩容,比 1.7 分段锁再提 45%+。

    十一、面试高频追问

    1. 为什么 1.8 放弃 Segment?粒度太粗,且维护 16 个数组指针占用内存;桶级锁已能满足极高并发。
    2. synchronized 性能差?1.8 对 synchronized 做了大量偏向锁/轻量锁优化,锁定时间极短(仅链表/树操作),CAS 失败概率低。
    3. CAS 自旋浪费 CPU?仅在空桶写入失败时自旋,冲突概率极低;扩容帮忙机制反而提升吞吐。
    4. 与 ConcurrentSkipListMap 区别?后者基于跳表,保证有序但 O(log n);CHM 无序 O(1),并发度更高。

    AI大模型学习福利

    作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

    一、全套AGI大模型学习路线

    AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

    因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取

    二、640套AI大模型报告合集

    这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

    因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获

    三、AI大模型经典PDF籍

    随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。


    因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获

    四、AI大模型商业化落地方案

    因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获

    作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量

    评论
    成就一亿技术人!
    拼手气红包6.0元
    还能输入1000个字符
     
    红包 添加红包
    表情包 插入表情
     条评论被折叠 查看
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值