- ✅
ConcurrentHashMap
的底层实现原理
- ✅ 与
HashMap
的区别
- ✅ JDK7 与 JDK8 的实现差异
- ✅ 核心方法源码分析(如
put
, get,computeIfAbsent
)
- ✅ 并发控制机制(CAS + synchronized)
- ✅ 使用注意事项与最佳实践
- ✅ 示例代码 + 图解流程
🧱 Java 并发编程:ConcurrentHashMap 原理与核心源码详解
一、ConcurrentHashMap 简介
✅ 是什么?
ConcurrentHashMap
是一个线程安全的哈希表实现,位于 java.util.concurrent
包下。
它解决了 HashMap
在并发环境下线程不安全的问题,并提供了比 Collections.synchronizedMap()
更高的并发性能。
✅ 适用场景
- 多线程共享数据结构;
- 高频读写操作;
- 缓存、计数器、状态管理等并发场景。
二、ConcurrentHashMap 与 HashMap 的对比
特性 |
HashMap |
ConcurrentHashMap |
是否线程安全 |
❌ 否 |
✅ 是 |
实现方式 |
数组+链表/红黑树 |
数组+链表/红黑树 + CAS + synchronized |
null 键值支持 |
✅ 支持 |
❌ 不支持 |
扩容机制 |
单线程扩容 |
✅ 并发扩容 |
锁粒度 |
整个 Map(全锁) |
✅ 分段锁(JDK7)→ 粒度更细(JDK8) |
三、JDK7 vs JDK8 实现差异
特性 |
JDK7 |
JDK8 |
数据结构 |
Segment 分段锁 |
Node 数组 + 链表/红黑树 |
锁机制 |
Segment 分段锁 |
synchronized + CAS |
扩容策略 |
每次扩容整个 Segment |
单个桶迁移,支持并发扩容 |
红黑树支持 |
❌ 不支持 |
✅ 支持(链表长度 ≥ 8) |
性能 |
中等 |
更高(细粒度锁) |
四、JDK8 底层结构图(Markdown 图形化)
[0] ── Node<K,V> (volatile)
[1] ── TreeNode / ForwardingNode / ReservationNode ...
[2]
...
[n]
- 每个桶首次插入时初始化;
- 使用
synchronized
锁住当前 Node 头节点;
- 扩容时使用
ForwardingNode
标记迁移状态;
- 支持并发扩容(transfer);
五、ConcurrentHashMap 构造函数详解
public ConcurrentHashMap(int initialCapacity,
float loadFactor,
int concurrencyLevel)
参数 |
含义 |
initialCapacity |
初始容量,默认 16 |
loadFactor |
负载因子,默认 0.75 |
concurrencyLevel |
并发级别(JDK8 已忽略) |
六、核心成员变量一览(JDK8)
transient volatile Node<K,V>[] table;
private transient volatile Node<K,V>[] nextTable;
private transient volatile long baseCount;
private transient volatile int sizeCtl;
七、put(K key, V value) 方法详解
✅ 源码逻辑(JDK8)
public V put(K key, V value) {
return putVal(key, value, false);
}
final V putVal(K key, V value, boolean onlyIfAbsent) {
if (key == null || value == null) throw new NullPointerException();
int hash = spread(key.hashCode());
int binCount = 0;
for (Node<K,