ConcurrentHashMap分段锁原理
请说明ConcurrentHashMap在JDK7和JDK8中的实现区别,以及如何保证线程安全。
回答
古法程序员
JDK7实现(分段锁Segment):
- 结构:Segment数组 + HashEntry数组(每个Segment继承ReentrantLock)。
- 锁粒度:对某个Segment加锁,默认16个Segment,支持16个并发写。
- get:不加锁(volatile读取Entry的value和next指针)。
- put:定位Segment后,tryLock获取锁,获取不到自旋+阻塞。
- size():先无锁累加两次,结果一致则返回;否则依次锁所有Segment重算。
JDK8实现(CAS + synchronized):
- 结构:Node数组 + 链表/红黑树(同HashMap)。
- 锁粒度:对链表/红黑树的头节点加锁,粒度更细。
- put:
- 数组位置空→CAS插入。
- 非空→synchronized(头节点)后遍历插入。
- 链表长度≥8→红黑树化(TreeBin)。
- get:volatile读取,不加锁。
- size():通过CounterCell数组累加,baseCount+Cells数组计数。
- transfer():多线程协助扩容。
JDK8改进:锁粒度更细(一个桶一个锁)、空间更小(去掉Segment类)、引入红黑树防哈希冲突攻击。