ConcurrentHashMap你面试被问过多少次?

你好,我是风一样的树懒,一个工作十多年的后端开发,曾就职京东、阿里等多家互联网头部企业。

点击下方👇关注公众号,带你一起复习后端技术,看看面试考点,补充积累技术知识,每天都为面试准备积累


ConcurrentHashMap 是 Java 中用于并发场景的线程安全哈希表,它在高并发下提供了较好的性能,同时避免了线程间的冲突问题。


01
ConcurrentHashMap 的核心原理


JDK 1.7:

  • 基于 分段锁机制(Segment-based Locking)。

  • 数据结构由多个 Segment 组成,每个 Segment 类似于一个小型的 HashMap,通过 ReentrantLock 实现线程安全。

  • 每个 Segment 维护自己的哈希桶数组和链表/树结构。

JDK 1.8:

  • 取消了 Segment,直接使用 CAS(Compare-And-Swap)+ synchronized。

  • 数据结构为数组(Node[])+ 链表 + 红黑树。

  • 在哈希冲突严重时,链表长度超过一定阈值(默认 8),会转换为红黑树,提升查询性能。


02
线程安全的实现机制


JDK 1.7 的分段锁
  • 整个 ConcurrentHashMap 被分为多个 Segment,每个 Segment 独立维护其内部的哈希桶。

  • 锁粒度更细:只锁住当前 Segment,避免了全表锁,从而提高并发性。

  • 每次操作(如插入、删除、读取等)只需要对相关的 Segment 加锁。

JDK 1.8 的改进
  • 采用 CAS + synchronized:


    • CAS 用于实现无锁操作,比如节点的插入。

    • 当 CAS 操作失败时,退而使用 synchronized。

  • 每个桶(数组中的一个槽)独立加锁,而非对整个结构加锁。

  • 红黑树优化:当链表长度较长时,转为红黑树,提升性能。


03
具体操作如何实现线程安全


插入操作
  • 根据 key 的 hash 值找到对应的桶(Node[] 的某个槽位)。

  • 使用 CAS 尝试更新(如果桶为空,直接插入;否则进入下一步)。

  • 如果 CAS 失败,则通过 synchronized 锁住对应的桶,并更新链表或红黑树。

读取操作
  • 通过计算哈希找到对应桶。

  • 直接读取桶中的链表或红黑树,无需加锁(链表或树的读操作是线程安全的,因为写操作会使用同步机制避免冲突)。

删除操作
  • 通过哈希值找到对应桶。

  • 使用 synchronized 锁住桶,安全地删除节点。

  • 如果节点为红黑树节点,维护红黑树的平衡。

扩容操作
  • 当负载因子超过阈值时,触发扩容(默认负载因子为 0.75)。

  • 创建一个新的更大容量的数组。

  • 数据迁移是分段完成的,多个线程可以并发地帮助扩容操作,减少停顿时间。


04
ConcurrentHashMap 的优势


高效的线程安全性:通过细粒度锁和无锁操作,减少锁的竞争,提高并发性能。

支持高并发:多线程可以同时操作不同的桶或节点。

性能优于 Hashtable:Hashtable 使用的是全表锁,性能瓶颈显著,而 ConcurrentHashMap 采用分段锁或 CAS,性能大幅提升。

弱一致性:在读写操作并发的情况下,允许读取到旧数据(最终一致性),从而提升性能。

使用场景

  • 高并发环境下的 Key-Value 数据存储
    如缓存系统、计数器、统计数据存储等。

  • 需要线程安全的哈希表
    替代 Hashtable 或 Collections.synchronizedMap()。

  • 对性能要求较高的场景
    如分布式系统的节点状态管理、会话管理等。


05
直击面试


5.1 ConcurrentHashMap 是如何实现线程安全的?

通过分段锁(JDK 1.7)或 CAS + synchronized(JDK 1.8)实现线程安全。


5.2 为什么 JDK 1.8 放弃了分段锁?

分段锁结构复杂且限制了扩展性,JDK 1.8 改为更简单高效的 CAS + synchronized 机制。


5.3 ConcurrentHashMap 如何进行扩容?

在负载因子超过阈值时触发扩容,数据迁移由多个线程并发完成。


5.4 ConcurrentHashMap 的弱一致性是什么?

读操作可能会看到旧数据(但不抛出异常),写操作最终会生效。


5.5 ConcurrentHashMap 中的链表转红黑树的条件?

单个桶的链表长度超过阈值(默认 8)。

今天的内容就分享到这儿,喜欢的朋友可以关注,点赞。有什么不足的地方欢迎留言指出,您的关注是我前进的动力!

END


扫码关注

一起积累后端知识
不积跬步,无以至千里
不积小流,无以成江海

喜欢此内容的人还喜欢

谈谈id那些事(五)——美团的 Leaf 的ID生成


一个阿里二面面试官必问的问题


谈谈id那些事(三)——阿里巴巴的 TDDL的ID生成


分享面试:mysql数据库索引失效的情况


面试常被忽略的问题——内存区域划分