0

0

什么是ConcurrentHashMap_分段锁(1.7)与CAS+Synchronized(1.8)原理

P粉602998670

P粉602998670

发布时间:2026-02-17 11:54:47

|

942人浏览过

|

来源于php中文网

原创

jdk 1.7 通过 segment 分段锁实现线程安全:默认16个segment,读操作无锁,写操作仅锁定对应segment,采用两次hash定位,支持并发度调整但需为2的幂;size()非强一致。

什么是concurrenthashmap_分段锁(1.7)与cas+synchronized(1.8)原理

ConcurrentHashMap 在 JDK 1.7 里怎么靠 Segment 分段锁实现线程安全

JDK 1.7 的 ConcurrentHashMap 不是给整个 map 加一把大锁,而是把数据拆成 16 个(默认)独立的 Segment,每个 Segment 是一个带锁的小型哈希表。读操作完全无锁,写操作只锁住对应的那个 Segment,其他段照常工作。

实际执行 put() 时会走两次 hash:第一次用高位 hash 定位到哪个 Segment,第二次用低位 hash 定位到该 Segment 内部数组的具体位置。这叫“锁分离”——不是锁数据,是锁数据所在的逻辑分区。

  • 默认并发度是 16,可通过构造函数传 concurrencyLevel 调整,但最终会被提升为最接近的 2 的幂次(如传 12 → 实际用 16)
  • 如果所有写操作都挤在同一个 Segment 上(比如 key 的高位 hash 总是一样),那并发度就白设了,性能退化成单线程
  • size() 方法要遍历全部 Segment 并加锁求和,可能阻塞、也可能返回估算值(尝试三次不一致就直接返回估算),不是强一致性

JDK 1.8 彻底去掉 Segment,改用 CAS + synchronized 锁桶节点

JDK 1.8 把结构简化回类似 HashMapNode[] 数组,但每个数组槽位(bin)的头节点自己就是锁对象。插入/更新时先用 cas 尝试无锁写入;失败则对那个 bin 的头节点加 synchronized,只锁这一小片区域。

Timebolt
Timebolt

视频静态过滤器,可以快速自动删除沉默镜头

下载

链表长度 ≥ 8 且数组长度 ≥ 64 时,链表转为红黑树——这是为了防止极端 hash 碰撞导致查找退化成 O(n)。树化后锁的粒度仍是单个 bin,不是整棵树。

  • put()get() 都不再需要两次 hash,一次定位到底,性能开销更低
  • 扩容是并发进行的:多个线程可协作搬运不同区段的节点,新老数组可同时服务读请求(通过 ForwardingNode 中转)
  • synchronized 锁的是 Node 对象,不是类或 this,避免锁升级带来的开销;但若多个线程反复竞争同一 bin,仍会触发偏向锁撤销甚至重量级锁

为什么不能简单认为 “1.8 一定比 1.7 快”

快慢取决于场景。高冲突低并发时,1.7 的分段锁可能因 segment 数固定、负载不均反而更卡;而 1.8 的细粒度锁在热点 key 场景下容易引发锁争用,甚至因频繁锁升级拖慢吞吐。

  • 1.7 的 Segment 是继承 ReentrantLock 的,有公平/非公平模式、可中断等待等开销;1.8 的 synchronized 更轻量,但不可中断、不支持条件队列
  • 1.7 的迭代器是弱一致性(不抛 ConcurrentModificationException),但可能漏掉刚插入的元素;1.8 迭代过程同样不阻塞写入,但结构变化(如树化、扩容)可能导致遍历跳过部分节点
  • 如果你的应用还依赖 segments.lengthsegment.getXXX() 这类 1.7 特有 API,升级到 1.8 会直接编译失败——它们全被删了

实际开发中该关注哪几个关键行为差异

别只盯着“线程安全”,更要盯住行为语义是否符合你业务预期。比如初始化、扩容策略、null 处理、以及某些方法在并发下的可见性边界。

  • computeIfAbsent() 在 1.8 是原子的,但在 1.7 不可用(得手写双重检查 + putIfAbsent()
  • 1.7 允许 key/value 为 null(虽然不推荐),1.8 明确禁止,put(null, v) 直接抛 NullPointerException
  • 1.8 的 mappingCount() 返回 long,解决 21 亿上限问题;1.7 的 size()int,超了就溢出
  • 无论哪个版本,都不保证遍历顺序;也不保证 keySet().iterator()values().iterator() 的遍历进度同步——别拿两个迭代器做交叉比对
JDK 版本切换时最容易被忽略的,不是语法报错,而是那些“没报错但行为变了”的地方:比如 size 统计不准、null 值突然炸了、或者某个自定义比较器在树化过程中触发了未预料的 compare 结果。这些坑不会在单元测试里冒头,只会在压测或上线后某天凌晨三点悄悄浮现。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

244

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

746

2024.03.01

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

750

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

571

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

234

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

209

2025.08.29

length函数用法
length函数用法

length函数用于返回指定字符串的字符数或字节数。可以用于计算字符串的长度,以便在查询和处理字符串数据时进行操作和判断。 需要注意的是length函数计算的是字符串的字符数,而不是字节数。对于多字节字符集,一个字符可能由多个字节组成。因此,length函数在计算字符串长度时会将多字节字符作为一个字符来计算。更多关于length函数的用法,大家可以阅读本专题下面的文章。

949

2023.09.19

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

675

2023.08.10

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

283

2026.02.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号