在Java里ConcurrentHashMap的核心原理_Java并发Map解析-java教程

ConcurrentHashMap 通过分段锁(JDK7)或CAS+volatile+synchronized单桶锁(JDK8)避免全局锁;get()无锁但依赖volatile可见性;computeIfAbsent可能重复计算;扩容采用分批迁移与协助机制保障读写不阻塞。

ConcurrentHashMap 是怎么避免全局锁的

它不靠 synchronized 锁整个 Map,而是把数据分段——早期 JDK 7 用 Segment 数组,每段独立加锁;JDK 8 彻底改用 Node 数组 + 链表/红黑树,配合 volatile + CAS + synchronized 锁单个桶(bin)来实现更细粒度控制。

这意味着:多个线程往不同桶里写,完全不互斥;只有哈希冲突撞到同一个桶,才可能触发同步块。实际压测中,并发写入吞吐量通常比 Hashtable 或 synchronized(new HashMap()) 高数倍。

注意点:

  • JDK 8 中 synchronized 锁的是 Node 首节点,不是整个链表或树,所以扩容时也能并发读写其他桶
  • size() 不再是 O(1),而是遍历所有 bin 的 baseCount 和每个 CounterCell 求和,可能有短暂延迟
  • 不要误以为“无锁”——它只是锁粒度小,put()、remove() 等关键操作仍有同步逻辑

为什么 computeIfAbsent 有时会重复计算

这是最常被踩的坑:computeIfAbsent 在 key 不存在时,会先调用你传入的 mappingFunction,再用 CAS 尝试插入结果;但如果多个线程同时发现 key 缺失,它们各自都会执行一遍函数,最后只有一条结果成功落库,其余计算白费,还可能引发副作用(比如重复发请求、创建对象)。

立即学习“Java免费学习笔记(深入)”;

典型场景:

  • 缓存穿透防护中用 computeIfAbsent("user:123", id -> loadFromDB(id)),并发请求下 loadFromDB 可能被调用多次
  • 函数里有 IO 或耗时操作,性能直线下滑

解决办法不是不用它,而是加一层双重检查或用 Future 包装:

夏夕资源网专注于CMS网站模板,主流语言整站网站源码下载,网站建设相关教程分享,好用的软件素材整合下载,提供一站式便捷自助服务。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,默认解压密码为"zy.lucklyus.top",如遇到无法解压的请联系管理员!
夏夕资源网-网站模板_免费源码_资源素材 » 在Java里ConcurrentHashMap的核心原理_Java并发Map解析-java教程
在线时间:12:00 - 22:00
关注微信公众号:微信公众号
站长邮箱:[email protected]
  • 运营天数: 1393+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 4023835+
  • 本周更新: 0+
  • 最后更新: 2026-03-16

本站指数

×
  • 运营天数: 1393+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 4023835+
  • 本周更新: 0+
  • 最后更新: 2026-03-16