concurrenthashmap 演进源于问题驱动:hashmap 线程不安全易成环或丢数据,hashtable 全表锁性能差;jdk 1.7 用分段锁(segment)提升并发度但粒度仍粗;jdk 1.8 改为桶级 synchronized + cas + 红黑树,实现动态细粒度并发。

面试时讲 ConcurrentHashMap 演进,关键不是罗列版本,而是用“问题驱动”的逻辑串起来:每一代改进,都是为解决上一代暴露的痛点。下面这三句话就能锚定主线,后面展开自然清晰:
为什么必须演进?——HashMap 不行,Hashtable 太重
HashMap 在多线程下会出问题:JDK 1.7 扩容用头插法,多线程同时操作可能把链表变成环,get 一调就死循环、CPU 拉满;JDK 1.8 虽改用尾插法避免成环,但依然不保证线程安全,数据可能覆盖或丢失。而 Hashtable 给所有方法加同一把 synchronized 锁,相当于整张表只允许一个线程读或写,高并发时性能断崖式下跌。
JDK 1.7:用“分段锁”把大锁拆成小锁
核心是引入 Segment 数组(默认 16 个),每个 Segment 是一个继承 ReentrantLock 的小型 HashMap(内部是 HashEntry 数组 + 链表)。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 写操作时,先根据 key 的 hash 定位到某个 Segment,只锁它,其他 Segment 照常工作 → 并发度理论最高 16
- 读操作完全无锁,靠 volatile 修饰的 value 和 next 字段保证可见性
- 但 Segment 本身是粗粒度单位:哪怕两个 key 落在同一个 Segment 的不同桶里,也要排队等锁
JDK 1.8:放弃 Segment,锁直接落到“桶”上
底层结构和 HashMap 1.8 对齐:Node 数组 + 链表 + 红黑树,并发控制改用 CAS + synchronized 组合。
- 数组初始化、扩容阈值更新等用 CAS,避免竞争
- 往空桶插入直接 CAS;非空桶则对链表头节点或红黑树根节点加 synchronized 锁 → 锁粒度细化到单个桶
- 链表长度 ≥ 8 且数组长度 ≥ 64 时转红黑树,防止长链表拖慢查询
- 扩容支持多线程协助:检测到正在扩容的桶(hash = MOVED),当前线程会主动帮着搬数据,不干等
一句话收尾:从 1.7 到 1.8,不是小修小补,是架构级重构——把“按段划分”的静态并发模型,升级为“按桶协作”的动态细粒度模型,更贴合现代多核 CPU 的并行特性。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










