ConcurrentHashMap(JDK 7/8)底层原理
1. ConcurrentHashMap 是为啥存在的?和 HashMap / Hashtable / Collections.synchronizedMap 的区别
1.1 HashMap
- 非线程安全:并发 put 可能导致数据丢失、链表成环(JDK7 扩容时尤其经典)等问题。
- 性能高但不能并发用。
1.2 Hashtable
- 线程安全:方法上
synchronized,整张表一把锁。 - 并发度差:读也要锁。
1.3 Collections.synchronizedMap(new HashMap<>())
- 也是整张表一把锁,实现方式是对外层 wrapper 的方法加
synchronized。 - 迭代时仍要手动同步,否则可能
ConcurrentModificationException。
1.4 ConcurrentHashMap
- 目标:高并发下更好的吞吐。
- JDK7:分段锁(Segment)提升并发度。
- JDK8:更细粒度(CAS + synchronized 在桶级别),读基本无锁,写锁粒度更小。
2. JDK7 ConcurrentHashMap:Segment 分段锁(理解历史,面试会问)
2.1 核心结构
ConcurrentHashMap内部是Segment<K,V>[] segments- 每个
Segment继承ReentrantLock,内部类似一个小 HashMap:HashEntry<K,V>[] table - 并发度主要由
segments数量决定(默认 16 级别的并发)。
2.2 put/get 简述
- get:定位到 segment,再在 segment 的 table 里查链表(读基本无锁,依赖 volatile 可见性)。
- put:定位 segment,然后
lock(),再按 HashMap 方式插入或替换,必要时扩容 segment 内 table。
2.3 优缺点
- 优点:相比 Hashtable 的全表锁,并发更强。
- 缺点:
- Segment 数量固定/半固定,会影响并发上限。
- 结构更重,锁粒度不够细,且实现复杂。
记一句话:JDK7 通过'锁分段'提升并发度。
3. JDK8 ConcurrentHashMap:Node + CAS + synchronized(现在主流)
3.1 核心字段与结构(必须会)
Node<K,V>[] table:主哈希表(桶数组)- :扩容时的新表


