ConcurrentHashMap源码详解
目录
- 概念说明
- 数据结构
- 线程安全
- HashMap示例
- 运行结果
- ConcurrentHashMap示例
- 运行结果
- 涉及技术
- Synchronized
- 概念
- 特性
- CAS(Compare And Swap)
- 概念
- 原理
- 代码演示
- 没有使用CAS的代码
- 运行结果
- 使用CAS的代码
- 运行结果
- 总结提升
概念说明
ConcurrentHashMap是Java中的线程安全的哈希表实现,它允许多个线程同时读取和写入数据,并且支持高并发访问。下面是ConcurrentHashMap、HashMap和HashTable的区别的二维表:

数据结构

ConcurrentHashMap和HashMap的数据结构是一样,由数组+链表+红黑树组成的。当向数组中出入的元素的hashcode都一样的情况下会形成链表结果,由于链表的时间复杂度是O(n),当链表过长的时候就会导致查询数据比较慢。所以当数组的长度为8的时候,链表结果就会转换成红黑树的结构,红黑树的时间复杂度是O(nlong)来提高查询数据的效率。以下是Map中涉及到的参数说明:
// 数组容量
private static final int MAXIMUM_CAPACITY = 1 << 30;
// 默认长度
private static final int DEFAULT_CAPACITY = 16;// 链表树化条件-是根据线程竞争情况和红黑树的操作成本进行设计的。
static final int TREEIFY_THRESHOLD = 8;
// 取消树化条件-为了避免过度的树化,防止内存占用过高。
static final int UNTREEIFY_THRESHOLD = 6; //链表结构中,每个节点只需要存储指向下一个节点的指针,而不需要存储节点的值。因此,链表只需要存储节点的引用,占用较少的内存空间。树结构中每个节点需要存储节点的值以及指向子节点的指针。
线程安全
通过使用HashMap和ConcurrentHashMap来对比一下,当在高并发的情况下是否会发生线程安全的问题
HashMap示例
public class HashMapUnsafeTest {public static void main(String[] args) throws InterruptedException {//演示HashMapMap<String, String> map = new HashMap<>();for (int i = 0; i < 30; i++) {String key = String.valueOf(i);new Thread(() -> {//向集合添加内容map.put(key, UUID.randomUUID().toString().substring(0, 8));//从集合中获取内容System.out.println(map);}, "").start();}}
}
运行结果

ConcurrentHashMap示例
public class ConcurrentHashMapSafe {public static void main(String[] args) throws InterruptedException {//演示ConcurrentHashMapMap<String, String> map = new ConcurrentHashMap<>();for (int i = 0; i < 30; i++) {String key = String.valueOf(i);new Thread(() -> {//向集合添加内容map.put(key, UUID.randomUUID().toString().substring(0, 8));//从集合中获取内容System.out.println(map);}, "").start();}}
}
运行结果

涉及技术
Synchronized
概念
synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程(例如线程A),运行到这个方法时,都要检查有没有其它线程B(或者C、 D等)正在用这个方法(或者该类的其他同步方法),有的话要等正在使用synchronized方法的线程B(或者C 、D)运行完这个方法后再运行此线程A,没有的话,锁定调用者,然后直接运行。即synchronized关键字解决的是多个线程之间访问资源的同步性,synchronized 翻译为中文的意思是同步,也称之为”同步锁“。它包括两种用法:synchronized 方法和 synchronized 块。
特性
「可见性 」:是指一个线程对共享变量进行修改,另一个线程立即得到修改后的新值。
「原子性 」:在一次或多次操作中,要么所有的操作都执行并且不会受其他因素干扰而中断,要么所有的操作都不执行。
「有序性 」:程序执行的顺序按照代码的先后顺序执行。编译器为了优化性能,有时候会改变程序中语句的先后顺序。
在使用多线程进行并发编程的时候,如果有多个线程来操作共享数据,很有可能共享数据的值会出现错乱,我们称之为线程安全问题。导致出现问题的原因有:可见性问题;原子性问题;有序性问题。这时候我们就可以通过使用synchronized 关键字来解决出现的问题。
CAS(Compare And Swap)
概念
在CAS中,有这样三个值:
V:要更新的变量(var)
E:预期值(expected)
N:新值(new)
比较并交换的过程如下:
判断V是否等于E,如果等于,将V的值设置为N;如果不等,说明已经有其它线程更新了V,则当前线程放弃更新,什么都不做。

原理
unsafe类——以下是类中涉及到的三个方法用来实现CAS效果的,这三个方法都是由native进行修饰的。具体的实现是由C++写的。

三个方法传入的参数都是一样的,只不过根据传入的类型不同选择不同的方法,第一个参数是当前这个对象,第二个参数线程之间共享的变量,第三个参数是预期值,第四个参数想要修改的值。
代码演示
没有使用CAS的代码
/*** @BelongsProject: demo* @BelongsPackage: com.example.threadpool.CAS* @Author: Wuzilong* @Description: 没有使用CAS的实例* @CreateTime: 2023-07-29 09:44* @Version: 1.0*/public class NoCASDemo {private static int counter = 0;public static void main(String[] args) throws InterruptedException {//线程一Thread thread1= new Thread(() -> {for (int i=0; i<10000;i++){counter++;}});//线程二Thread thread2= new Thread(() -> {for (int i=0; i<10000;i++){counter++;}});//执行线程thread1.start();thread2.start();//等待执行完线程1和2thread1.join();thread2.join();System.out.println("查看counter的总数"+counter);}}
运行结果



多次运行程序会发现counter的总数是不一样的,说明有的线程操作的是同一个数值,导致两次i++的结果是一样的。
使用CAS的代码
/*** @BelongsProject: demo* @BelongsPackage: com.example.threadpool.CAS* @Author: Wuzilong* @Description: 使用CAS的实例* @CreateTime: 2023-07-29 09:36* @Version: 1.0*/public class CASDemo {private static AtomicInteger counter = new AtomicInteger(0);public static void main(String[] args) throws InterruptedException {//线程一Thread thread1= new Thread(() -> {for (int i=0; i<10000;i++){increment();}});//线程二Thread thread2= new Thread(() -> {for (int i=0; i<10000;i++){increment();}});//执行线程thread1.start();thread2.start();//等待执行完线程1和2thread1.join();thread2.join();System.out.println("查看counter的总数"+counter.get());}public static void increment() {int currentValue;int newValue;do {//获取counter对象的value值currentValue = counter.get();//将counter对象的value值加1newValue = currentValue + 1;} while (!counter.compareAndSet(currentValue, newValue));}}
运行结果



多次运行程序发现counter的总数都是20000,这就说明使用了CAS之后不会出现线程安全的问题,当共享变量与预期值不一致的时候就取消了当前线程的操作。
总结提升
ConcurrentHashMap是一个线程安全的哈希表实现,它通过锁分段技术实现了高效的并发性能,支持高效的并发更新和弱一致性的迭代器。但需要注意的是,ConcurrentHashMap不支持存储null键和null值。在多线程环境下,使用ConcurrentHashMap可以提高并发性能,并且无需额外的同步措施。

相关文章:
ConcurrentHashMap源码详解
本文已收录于专栏 《Java》 目录 概念说明数据结构线程安全HashMap示例运行结果ConcurrentHashMap示例运行结果 涉及技术Synchronized概念特性 CAS(Compare And Swap)概念原理代码演示没有使用CAS的代码运行结果使用CAS的代码运行结果 总结提升 概念说明 ConcurrentHashMap是Ja…...
医疗流程自动化盛行,RPA成为医疗保健行业的重点应用技术
随着我们进入新的科技纪元,机器人流程自动化(RPA)正快速地改变着我们的游戏规则。简单来说,RPA 就是模仿人类与电子系统的互动,自动化执行重复性的任务和操作序列。 医疗保健领域中,RPA 的应用具备巨大的潜…...
Java 版 spring cloud + spring boot 工程系统管理 工程项目管理系统源码 工程项目各模块及其功能点清单
工程项目各模块及其功能点清单 一、系统管理 1、数据字典:实现对数据字典标签的增删改查操作 2、编码管理:实现对系统编码的增删改查操作 3、用户管理:管理和查看用户角色 4、菜单管理:实现对系统菜单的增删改查操…...
java重试机制实现方案
本文内容是目前团队内小磊同学对重试机制实现方案的梳理总结。 从为什么需要重试的背景开始,到重试的场景,大致的一些设计思路,最后通过两个成熟的retry组件进行案例讲解,理论实战。 背景 重试是系统提高容错能力的一种手段。在一…...
参数量仅有50KB的超轻量级unet变种网络egeunet【参数和计算量降低494和160倍】医疗图像分割实践
今天看到一篇挺有意思的文章,做的是跟医疗图像分割相关的工作,但是不像之前看到的一些工作一味地去追求高精度,因为医疗领域本身就是一个相对特殊的行业,对于模型产生的结果的精确性要求是很高的,带来的是参数量级的庞…...
Android10 Settings系列(三)根据需求动态添加删除一级菜单、二级菜单的设置项
一 、背景 当时遇到定制需求,需要根据实际需要隐藏Settings的菜单项,于是开始了寻找方法 二 、准备工作 在看了一下源码,经过尝试后,确认生效后,就简单说明一下Settings中布局中主要组成元素 Settings中的菜单项是由 PreferenceScreen 和Preference组成的。其中Prefer…...
51单片机——串行口通信
目录 1、51单片机串口通信介绍 2、串行口相关寄存器 2.1 、串行口控制寄存器SCON和PCON 2.1.1 SCON:串行控制寄存器 (可位寻址) 2.1.2 PCON:电源控制寄存器(不可位寻址) 2.2、串行口数据缓冲寄存器SBUF 2.3、从机地址控制…...
洛谷题单 Part 6.7.1 矩阵
应队友要求,开始学线性代数,具体路线是矩阵 → \rightarrow →高斯消元 → \rightarrow →线性基。为多项式做个准备 P3390 【模板】矩阵快速幂 题面 板子,用结构体写的,感觉有点丑,一会儿看看题解有没有写得好看的 …...
Spring中c3p0与dbcp配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schem…...
Flutter 添加 example流程
一、已有Flutter工程(命令)添加 example 1、cd 工程(flutter_plugin ,是自己创建的)根目录 例: flutter create example 执行命令创建example PS:cd example 后执行flutter doctor 后就可以看到效果 2、如果需要指定iOS/Android 语言,请添加…...
数据治理8种方法
数据治理8种方法 8种方法,分别是:顶层设计法、技术推动法、应用牵引法、标准先行法、监管驱动法、质量管控法、利益驱动法、项目建设法。 事先声明,这些方法论都是向各位大佬学习来的,也有部分是项目中实操得来的,并非…...
大模型成互联网真正蜕变的标志,亦是各种新技术开始衍生的标志
以往,我们看到了以区块链、元宇宙为代表的诸多新物种的出现,但是,它们始终都没有逃脱仅仅只是一个概念和噱头的宿命,它们始终都没有走出一条可持续的发展道路。说到底,它们仅仅只是一个没有实现商业闭环的概念而已&…...
指针进阶详解---C语言
❤博主CSDN:啊苏要学习 ▶专栏分类:C语言◀ C语言的学习,是为我们今后学习其它语言打好基础,C生万物! 开始我们的C语言之旅吧!✈ 目录 前言: 一.字符指针 二.指针数组 三.数组指针 四.数组、指针参数 …...
设计模式思考,简单工厂模式和策略模式的区别?
最近学习了设计模式,学到简单工厂模式和策略模式的时候想,这两个模式不是一样嘛,仔细思考之后发现大体设计思路是一样的,但是细节却有所不一样。 简单工厂模式 简单工厂模式是一种创建型设计模式,它主要涉及对象的创建…...
Java - sh 脚本启动 jar 包等服务 - sh 脚本模板 - 适用于任何类似的服务启动
sh 脚本模板 该模板,每次运行一次都会 kill 掉原来的服务,然后重新启动 jar 包服务 #!/bin/bash# 定义Java进程的名称 APP_NAMEyour-app-name.jar# 定义Java进程的日志文件路径 LOG_PATH/var/log/your-app-name.log# 定义备份日志文件的目录 BACKUP_DI…...
MySQL高级篇第5章(存储引擎)
文章目录 1、查看存储引擎2、设置系统默认的存储引擎3、设置表的存储引擎3.1 创建表时指定存储引擎3.2 修改表的存储引擎 4、引擎介绍4.1 InnoDB 引擎:具备外键支持功能的事务存储引擎4.2 MyISAM 引擎:主要的非事务处理存储引擎4.3 Archive 引擎…...
openssl 命令行国密sm2的签名验签操作
快速链接: . 👉👉👉 个人博客笔记导读目录(全部) 👈👈👈 付费专栏-付费课程 【购买须知】: 密码学实践强化训练–【目录】 👈👈👈 生成EC私钥: openssl ecp…...
开源代码分享(9)—面向100%清洁能源的发输电系统扩展规划(附matlab代码)
1.背景介绍 1.1摘要 本文提出了一种新颖的建模框架和基于分解的解决策略,将随机规划(SP)和鲁棒优化(RO)相结合,以应对协调中长期电力系统规划中的多重不确定性。从独立系统运营商(ISOÿ…...
为 Google Play 即将推出基于区块链的内容政策做好准备
作者 / Joseph Mills, Group Product Manager, Google Play 作为一个平台,Google Play 一直致力于帮助开发者将创新理念变为现实。Google Play 上托管了许多和区块链相关的应用,我们深知合作伙伴们希望扩展这些应用,并利用 NFT 等代币化数字资…...
查找-多路查找详解篇
多路查找树 多路查找树(Multway Search Tree)是一种高级的树形数据结构,它 允许每个节点有多个子节点(通常大于等于2)。多路查找树的每个节点 可以存储多个关键字和对应的值。分类 2-3树(2-3 Tree&#x…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
