讲师中心 微信公众号
AI工具推荐 视频效率加速

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

千雪吖_7200

千雪吖_7200

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

|

963人浏览过

|

来源于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 把结构简化回类似 HashMap 的 Node[] 数组,但每个数组槽位(bin)的头节点自己就是锁对象。插入/更新时先用 cas 尝试无锁写入;失败则对那个 bin 的头节点加 synchronized,只锁这一小片区域。

链表长度 ≥ 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.length 或 segment.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工具

更多
讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

UP简历
UP简历 Hot

一款AI办公效率工具,主要用于基于AI技术的免费在线简历制作工具,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

墨刀AI
墨刀AI Hot

一款AI图像与设计工具,主要用于产品经理的专属智能体,适合需要提升相关任务效率的用户。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

相关专题

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

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

549

2023.09.22

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

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

1698

2024.03.01

string转int
string转int

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

6539

2023.08.02

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

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

3165

2024.08.29

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

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

4088

2025.08.29

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

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

2805

2025.08.29

length函数用法
length函数用法

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

1867

2023.09.19

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

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

4298

2023.08.10

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

0

2026.10.22

热门下载

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

精品课程

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn