ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

字节二面必问:ConcurrentHashMap JDK1.7分段锁 vs JDK1.8 CAS+synchronized 核心差异

2026/8/20 10:32:09 拓冰建站 浏览量
字节二面必问:ConcurrentHashMap JDK1.7分段锁 vs JDK1.8 CAS+synchronized 核心差异 前言ConcurrentHashMap 是Java并发集合高频面试压轴题很多人只记住1.7分段锁、1.8取消分段锁。面试官深挖分段锁原理是什么为什么1.8废弃分段锁改用synchronized两者并发粒度、锁竞争、内存开销、扩容差异是什么synchronized性能为什么超越ReentrantLock本文完整对比两套实现梳理底层原理、优缺点、面试标准答案。一、JDK 1.7 实现Segment 分段锁ReentrantLock底层结构ConcurrentHashMap Segment[] HashEntry[] 链表Segment 继承ReentrantLock本质是独立锁每个Segment内部持有一张HashEntry数组分段思想把整个大哈希表切分成若干独立分段默认Segment数量16也就是最多支持16个线程并发写互不抢占不同Segment锁。put流程简要根据key的hash定位到对应的Segment获取该Segment的ReentrantLock独占锁在Segment内部HashEntry数组执行写入、冲突处理释放锁。核心特点锁粒度Segment段级别只要操作落在同一个Segment就会竞争同一把锁哪怕操作不同桶。扩容每个Segment独立扩容互不影响冲突结构只有链表没有红黑树size()统计尝试无锁统计多次冲突时锁住所有Segment统计开销巨大。明显缺陷默认分段16并发上限被固定想要更高并发只能调大Segment数量内存开销暴涨锁粒度偏大同一个Segment内多个桶互相阻塞Segment对象本身占用额外内存内存占用高size操作需要锁住全部分段并发统计性能差。二、JDK 1.8 实现CAS synchronized取消Segment底层结构和HashMap结构保持一致Node[] 链表 红黑树彻底移除Segment数组。核心机制空桶位置使用CAS自旋尝试插入Node无锁桶已有数据锁住桶头节点Node使用synchronized锁粒度哈希桶单个index级别粒度远小于分段锁冲突链表长度≥8数组≥64 → 转为红黑树扩容借助ForwardingNode转移节点支持并发扩容。put简要流程hash定位桶下标如果桶为空CAS尝试新建节点CAS失败则自旋重试桶不为空对桶首节点synchronized加锁在链表/红黑树执行新增、覆盖判断是否触发扩容支持多线程协助迁移数据。三、核心差异对照表对比维度JDK1.7 Segment分段锁JDK1.8 CAS synchronized底层数据结构Segment[] HashEntry数组 单向链表Node数组 链表 红黑树锁对象SegmentReentrantLock哈希桶头Nodesynchronized锁粒度分段级别一段内多个桶共享一把锁桶级别只锁住当前操作的单个桶并发上限受Segment数量限制默认最多16个写线程并发理论更高只要操作不同桶无锁竞争空桶插入必须获取Segment锁CAS无锁插入性能更好冲突结构只有链表链表红黑树查询O(n)优化为O(logn)扩容方式每个Segment独立扩容无法跨段协助支持多线程并发协助迁移ForwardingNodesize()计算竞争激烈时锁住全部Segment开销极大使用baseCount CounterCells无锁统计性能大幅提升内存开销大量Segment对象内存占用更高移除Segment内存占用更低锁性能ReentrantLockAQS实现竞争激烈优势尚可synchronized经过JDK优化偏向锁、轻量级锁、重量级锁低竞争场景性能更好四、高频疑问为什么1.8放弃ReentrantLock改用synchronized锁粒度细化带来收益更大分段锁一段内多个桶互相阻塞1.8只锁单个桶极大降低锁竞争概率。JVM持续优化synchronizedJDK1.6之后引入偏向锁、轻量级锁、自适应自旋低并发场景下synchronized性能优于ReentrantLock只有高持续竞争场景ReentrantLock优势明显。减少对象内存消耗移除Segment数组不需要维护大量ReentrantLock实例。CAS配合无锁操作空桶直接CAS插入很多场景甚至不需要触发锁。五、并发扩容区别重点面试加分JDK1.7各个Segment独立扩容线程只能扩容自己命中的Segment无法协助其他分段迁移JDK1.8引入ForwardingNode标记正在迁移的桶其他线程put/get发现该节点会协助参与数据迁移加速扩容过程。六、高频面试误区纠正❌ 误区11.8完全不再使用锁只用CAS纠正CAS只处理空桶桶存在元素时依旧使用synchronized独占锁。❌ 误区2synchronized性能一定比ReentrantLock差纠正要看竞争程度低竞争下synchronized轻量级锁性能更优高持续竞争ReentrantLock略占优势但1.8通过缩小锁粒度大幅降低竞争。❌ 误区31.7最多只能16个线程并发写入纠正默认Segment16可以通过构造参数提升但会增加内存成本。❌ 误区4JDK1.7支持红黑树纠正不支持只有链表。七、面试满分口述标准答案直接背诵JDK1.7 ConcurrentHashMap采用Segment分段锁底层是Segment数组HashEntry链表。Segment继承ReentrantLock锁粒度为分段级别同一分段内所有桶共用一把锁默认16个分段并发写入上限受分段数量限制不支持红黑树扩容各分段独立进行。JDK1.8彻底移除Segment底层结构与HashMap一致采用CAS synchronized方案空桶通过CAS无锁插入桶存在数据时锁住桶头节点锁粒度缩小至单个哈希桶。同时引入红黑树优化长链表查询支持多线程并发协助扩容size统计采用无锁计数器优化。相比于分段锁1.8锁粒度更小、并发能力更强、内存占用更低同时依靠JVM对synchronized持续优化综合性能优于旧版本分段锁方案。总结1.7核心Segment ReentrantLock锁粒度粗1.8核心取消分段CAS自旋 桶级synchronized粒度更细新增红黑树、并发协助扩容、无锁计数锁粒度细化是版本改动最核心的目的。标签#Java面试 #ConcurrentHashMap #分段锁 #JDK1.7 #JDK1.8 #并发集合 #后端面试