jdk7采用分段锁(segment+reentrantlock),锁粒度为整个segment;jdk8改用cas+synchronized,锁粒度细化至桶头node节点,并支持红黑树优化与多线程协作扩容。

ConcurrentHashMap 在 JDK 7 和 JDK 8 中的锁机制有本质性差异:JDK 7 用的是分段锁(Segment + ReentrantLock),而 JDK 8 改为更细粒度的桶头节点锁,配合 CAS 和 synchronized 实现线程安全。
JDK 7:基于 Segment 的分段锁
ConcurrentHashMap 内部维护一个 Segment 数组(默认 16 个),每个 Segment 继承 ReentrantLock,相当于一个“小型 Hashtable”。每次 put 或 get 操作先定位到对应 Segment,再对该 Segment 加锁。
- 锁粒度是整个 Segment,包含多个 HashEntry 桶,即使只操作一个桶也要锁住整段
- Segment 数量固定,无法动态扩容,高并发下容易出现部分 Segment 竞争激烈、其余空闲的情况
- size()、clear() 等全表操作需遍历所有 Segment,加锁开销大,且采用弱一致性设计(如多次重试 + 不保证绝对准确)
JDK 8:CAS + synchronized 控制桶级锁
彻底移除 Segment,底层结构变为 Node[] 数组,每个桶(数组槽位)的首节点(Node)作为同步单元。插入、更新等操作优先尝试无锁的 CAS,失败后再对首节点加 synchronized 锁。
- 锁粒度降到单个桶的头节点,不同桶之间完全无锁竞争
- CAS 用于初始化桶、插入首个节点、扩容标记等场景,减少锁使用频率
- synchronized 锁定的是具体 Node 对象(非 this),避免全局锁开销,且 JVM 对轻量级锁做了深度优化
关键影响:并发性能与行为变化
锁机制的演进直接带来三方面变化:
- 扩容支持多线程协作:JDK 8 中多个线程可同时参与迁移(helpTransfer),而 JDK 7 是各 Segment 独立扩容,整体协调弱
- 哈希冲突处理升级:JDK 8 在链表过长(≥8)且表容量 ≥64 时转为红黑树,查找从 O(n) 降至 O(log n),这对锁持有时间也有间接优化
- 内存可见性保障统一:JDK 8 中 Node 的 val 和 next 字段都用 volatile 修饰,配合 CAS 和 synchronized,确保读写及时可见,不再依赖 Segment 的锁语义
不复杂但容易忽略:JDK 8 的改变不只是“换了个锁”,而是以数据结构简化为前提,把并发控制下沉到最基础的操作单元,从而在高并发、大数据量场景下更稳定高效。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











