Text
# Java ConcurrentHashMap 原理`ConcurrentHashMap` 是 Java 并发包(`java.util.concurrent`)提供的线程安全 **哈希表**,相比 `Hashtable` 和同步 `HashMap`,它具有 **更高的并发性能**。  不同 JDK 版本实现略有不同:- JDK 7:分段锁(Segment + ReentrantLock)- JDK 8:CAS + synchronized + 链表 / 红黑树,无段锁---# 一、JDK 7 原理(分段锁 SegmentedLock)1. 数据结构

ConcurrentHashMap
├─ Segment[] segments
├─ HashEntry[]

Text
- `Segment` 是哈希表的一个小段,内部继承 `ReentrantLock`- 每个 `Segment` 包含一个哈希桶数组 `HashEntry[]`- 每个哈希桶是链表,存储 `key-value`2. 并发策略- 不同 `Segment` 之间可以 **并发访问**- 每个 `Segment` 内使用锁保证线程安全- 读操作(get)通常 **不加锁**,因为 volatile 保证可见性3. 访问流程```textget(key):  - 计算 hash  - 定位 Segment  - 遍历桶链表查找 key
Text
put(key, value):  - 计算 hash  - 定位 Segment  - 上 Segment 锁  - 插入 / 更新链表  - 解锁
  1. 并发性能
  • 默认 16 段(Segment)
  • 不同段之间操作互不影响
  • 最大并发数 = Segment 数量

二、JDK 8 原理(无段锁,CAS + synchronized)

  1. 数据结构
Text
ConcurrentHashMap ├─ Node<K,V>[] table       ├─ Node<K,V> 链表 / 树(红黑树)
  • Segment 被移除
  • 使用 数组 + 链表 / 红黑树 存储
  • Node 对象包含 key、value、hash、next
  1. 并发策略
  • 读操作无需锁,使用 volatile 保证可见性
  • 写操作
    • 链表为空 → 使用 CAS 插入
    • 链表非空 → synchronized 加锁单个桶(链表头)插入
  • 当链表过长(> 8) → 转换为红黑树,降低查找复杂度 O(n) → O(log n)
  1. 访问流程
Text
get(key):  - 计算 hash  - 定位桶 index = hash & (table.length - 1)  - 遍历链表 / 红黑树
Text
put(key, value):  - 计算 hash  - 定位桶  - 使用 CAS 尝试插入  - 如果失败:      - synchronized 当前桶头,插入 / 更新      - 如果链表过长 → 转红黑树
  1. 扩容(resize)
  • JDK 8 ConcurrentHashMap 支持 分段迁移,不一次性全表锁
  • 扩容过程可以被多个线程协作完成
  • 保证 读写不阻塞

三、关键特性

  1. 高并发读写
    • JDK 7:分段锁
    • JDK 8:CAS + synchronized + 链表/红黑树
  2. 非阻塞读取
    • get 不加锁,读性能高
  3. 支持并发扩容
    • JDK 8 扩容无全表阻塞
  4. 链表 → 红黑树
    • 当桶内元素过多,性能从 O(n) → O(log n)
  5. 线程安全
    • 保证 原子操作(putIfAbsent, remove, replace)

四、面试常问点

  1. JDK 7 vs JDK 8 的区别?
    • 7:Segment 分段锁,锁粒度较粗
    • 8:无 Segment,CAS + synchronized + 链表/树
  2. 如何保证读操作线程安全?
    • Node.value 使用 volatile
    • get 不加锁
  3. put 操作线程安全如何实现?
    • CAS + synchronized 锁桶头
    • 保证链表插入/更新原子性
  4. 扩容是如何并发进行的?
    • 使用 forwarding Node + 分段迁移
    • 多线程协作完成桶迁移
  5. 链表过长怎么优化?
    • 转红黑树

五、总结

  • JDK 7:Segment + ReentrantLock
  • JDK 8:CAS + synchronized + 链表/红黑树
  • 高并发场景读性能高,写性能通过局部锁保证
  • 扩容支持并发,保证系统可用性

核心理念

Text
减少锁粒度非阻塞读局部锁写链表转红黑树

面试高分回答:

“ConcurrentHashMap 在 JDK 8 中采用无段锁设计,读操作不加锁,写操作对单个桶同步,使用 CAS 提升并发,链表过长时转红黑树,同时扩容可以并发进行。相比 JDK 7 的分段锁,实现了更高的并发性能和扩展性。”

Text