concurrenthashmap在jdk1.7中采用分段锁(segment)机制,将哈希表分为默认16个独立segment,每个segment继承reentrantlock并维护自己的hashentry数组,写操作锁定对应segment,读操作依赖volatile无锁;其局限在于segment级锁粒度仍粗、内存冗余、链表无平衡能力,故jdk1.8废弃该设计,改用cas+synchronized锁头节点。

ConcurrentHashMap 在 JDK 1.7 中采用分段锁(Segment Lock)机制,核心是把整个哈希表逻辑切分为多个独立段,每段自成一个小 HashMap,并配一把独立锁。
分段锁的基本结构
默认初始化 16 个 Segment,每个 Segment 继承 ReentrantLock,内部维护自己的 HashEntry 数组、size 计数器和扩容阈值。key 的 hash 值经位运算后决定归属哪个 Segment,线程只锁定对应段,其余段可并发操作。
- Segment 数组长度固定,不可动态增减,默认并发度为 16
- 每个 Segment 内部仍是“数组 + 链表”,不支持红黑树优化
- HashEntry 的 value 和 next 字段用 volatile 修饰,保证读操作无锁但可见
分段锁的加锁行为
写操作(如 put)需先定位 Segment,再调用其 put() 方法并尝试获取该 Segment 的锁;若失败则阻塞等待。读操作全程无锁,依赖 volatile 语义实现弱一致性。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 不同 Segment 之间完全无锁竞争,适合多线程分散写入场景
- 同一 Segment 内所有写操作串行化,即使操作不同桶也需排队
- 扩容仅针对单个 Segment,不影响其他段,但各 Segment 扩容互不同步
分段锁的主要局限
虽然比 Hashtable 的全局锁进步明显,但设计上存在三方面硬伤:
- 锁粒度仍是 Segment 级别,无法避免同段内多线程对不同桶的竞争
- 每个 Segment 携带完整元数据(如 threshold、count、table),小容量下内存冗余严重
- 链表过长时查询退化为 O(n),缺乏自动平衡能力,高冲突场景性能下滑明显
为什么后来被 JDK 1.8 彻底废弃
这些瓶颈在高并发、大数据量场景下愈发突出,促使 JDK 1.8 彻底重构:去掉 Segment 层,改用 CAS + synchronized 锁头节点,配合数组+链表+红黑树结构,将锁粒度从“段”降到“桶”,同时引入 volatile + CAS 保障无锁读写与可见性。分段锁就此成为历史设计范式。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










