concurrenthashmap在jdk 7中通过segment类继承reentrantlock实现分段锁,segment数组仅存储segment实例;jdk 8起改用cas+synchronized优化并发性能。

ConcurrentHashMap 在 JDK 7 及之前版本 中确实使用了 Segment 数组 + ReentrantLock 的分段锁机制,但需要澄清一个关键点:
Segment类本身继承自ReentrantLock,而不是“Segment 数组继承 ReentrantLock”。
数组只是存储多个Segment实例的容器,真正继承ReentrantLock的是Segment这个内部类。
✅ Segment 是 ReentrantLock 的子类
在 JDK 7 的 ConcurrentHashMap 源码中,Segment 定义如下(简化):
static final class Segment<k> extends ReentrantLock implements Serializable {
// ...
}</k>
这意味着每个 Segment 实例既是锁(可调用 lock()/unlock()),又封装了一小部分哈希桶(HashEntry[] table),负责保护其管辖范围内的键值对。
? 为什么这样设计?
-
分段加锁:把整个哈希表切分为多个
Segment(默认 16 个),不同线程操作不同段时互不阻塞。 -
复用 AQS 机制:
ReentrantLock基于 AQS(AbstractQueuedSynchronizer),天然支持可重入、公平/非公平策略、条件队列等,Segment直接复用这些能力,无需重复实现锁逻辑。 -
轻量级同步粒度:相比
Hashtable全表锁或Collections.synchronizedMap的粗粒度锁,Segment提升了并发读写性能。
? Segment 数组的作用
final Segment<k>[] segments;</k>
-
segments是一个Segment引用数组,长度为concurrencyLevel(构造时指定,默认 16)。 - 每个
Segment管理一部分HashEntry[](即子哈希表),通过二次哈希(hash & (segments.length - 1))定位到具体Segment。 - 调用
put/remove等方法时,先定位Segment,再调用其lock()加锁 —— 因为它本身就是ReentrantLock子类。
例如:
Segment<k> s = segmentFor(hash); s.lock(); // 直接调用继承自 ReentrantLock 的 lock() // ... 执行 put 操作 s.unlock();</k>
⚠️ 注意:JDK 8+ 已彻底移除 Segment
- JDK 8 开始,
ConcurrentHashMap重构为 CAS + synchronized + 红黑树 方案。 - 不再有
Segment类,也不再继承ReentrantLock。 - 锁的粒度进一步细化到单个链表头节点(Node),用
synchronized (f)控制,配合UnsafeCAS 操作。
所以如果你看到 “ConcurrentHashMap 继承 ReentrantLock”,那一定是指 JDK 7 的 Segment 实现方式,且准确说是 Segment 类继承,不是数组、也不是 ConcurrentHashMap 本身。
✅ 总结要点
-
Segment是ReentrantLock的子类,因此每个Segment实例天然具备锁能力; -
segments数组只是持有多个Segment对象,不涉及继承关系; - 分段锁靠
hash → segmentIndex → lock()三级定位实现并发控制; - JDK 8+ 已弃用该设计,改用更轻量的
synchronized+ CAS。
不复杂但容易忽略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











