concurrenthashmap是java线程安全高效哈希表,jdk1.7用分段锁、jdk1.8改用cas+桶级synchronized,禁止null键值以消除语义歧义,读操作无锁依赖volatile,写操作细粒度加锁,兼顾性能与安全性。

ConcurrentHashMap 不是孤立的工具,而是 Java 并发编程知识网络中的关键枢纽节点。要围绕它构建系统、可迁移、能应对中高级面试的知识图谱,核心不是死记它的 API,而是把它当作“连接器”,主动向三个方向延伸:向下锚定内存模型与锁机制,横向打通集合与线程协作,向上对接业务场景与设计约束。
向下深挖:从 CHM 操作反推 JMM 与锁原理
CHM 的每个典型操作背后都对应着明确的并发原语:
- get() 不加锁却线程安全 → 源于 Node.val 和 next 字段的 volatile 修饰,这是 JMM 中“可见性”的落地;table 数组引用本身也是 volatile,保障扩容后新数组地址对所有线程立即可见
- put() 只锁单个桶头节点 → 说明 synchronized 锁的是具体 Node 或 TreeBin 实例,而非整个 map;这引出“锁对象粒度”概念,并自然关联到轻量级锁、偏向锁等 JVM 锁优化机制
- computeIfAbsent() 原子完成查+算+存 → 内部依赖 CAS 尝试更新 + synchronized 临界区兜底,是典型的“无锁+有锁”混合策略,可对比 AtomicInteger 的 compareAndSet 理解其适用边界
横向串联:在集合体系中定位 CHM 的取舍逻辑
不能只说“CHM 是线程安全的 HashMap”,而要讲清它为什么被设计成这样、牺牲了什么、换来了什么:
- 它不允许 null key/value,不是疏忽,而是为避免在多线程下 get(null) 返回 null 时无法区分“键不存在”还是“值为 null”,这是对语义确定性的主动约束
- 它的迭代器是弱一致性(weakly consistent),不抛 ConcurrentModificationException,但也不保证反映最新修改 —— 这是用“读的模糊性”换取“读的无锁性”,和 CopyOnWriteArrayList 的“写时复制”形成鲜明对比
- 对比 Hashtable 和 Collections.synchronizedMap,CHM 的优势不在“更安全”,而在“更少阻塞”:前者是全表锁,后者是方法级 synchronized,而 CHM 把锁拆到桶级别,把串行化降到最低
向上映射:用真实并发问题驱动知识闭环
把 CHM 放回业务现场,才能激活整张图谱:
- 缓存击穿场景下,get + putIfAbsent 组合可能失效(两次调用间存在空隙),必须升级为 computeIfAbsent 或 merge,这直接关联到“复合操作原子性”这一并发核心痛点
- 做计数统计时,若仅用 put(key, map.get(key)+1),结果必然错误 —— 因为 get 和 put 是两个非原子步骤;正确解法是 compute(key, (k,v) -> v == null ? 1 : v + 1) 或配合 LongAdder 使用,这里就串起了“竞态条件识别”“原子更新策略选择”“性能扩展性考量”三条线
- 在 Spring Bean 初始化中若注入 ConcurrentHashMap,需注意其构造时机与单例生命周期的关系;若该 map 被多个 @Async 方法共享,还要考虑是否需进一步封装为线程安全的业务服务,这就把并发容器拉进了框架层协同的语境
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











