编程(43)----------ConcurrentHashMap

news2024/12/24 8:36:40

在多线程中使用哈希表, 首先是不能使用HashMap的. 因为其本身并非线程安全. 与其相反HashTable则是安全的. 其原因在于本身给关键的方法加了锁. 但即便如此, 与HashTable相比, 更推荐使用ConcurrentHashMap. 其原因在于, 它在HashTable的基础上做了较多的优化:

上述提到, HashTable线程安全的前提是加锁. 但其加锁是对方法加锁. 这意味着其加锁对象是this, 加了一把大锁. 

                                                                            

如图所示, 在这个哈希表中, 假设有两个线程要对key为1的链表中的a, b进行增删查改. 很显然, 若不进行加锁, 就会引发线程安全. 因此当其中一个线程访问时, 整个哈希表都相当于加了一个大锁, 进而防止线程安全.

但如果两个线程访问的是c和d呢? 很显然这个时候其实无需加锁. 因为二者根本是在不同的链表上的. 在这种情况下加锁毫无意义. 二者访问根本不会收到影响. 只会白白因为加锁而浪费资源和时间.

因此, ConcurrentHashMap优化的第一个地方就是将这个大锁进行细化. 在JDK1.8以前, 是将哈希表数组中的每几个进行上锁. 但是这样效果并不好, 之后就直接进行单独加锁. 即将每个链表的头结点作为加锁对象.  这样既可以保证访问同一个链表时加锁, 不同链表之间也能有效同时进行访问.

                                                                             

 ConcurrentHashMap第二个优化的地方是其只针对写操作加锁. 也就是说ConcurrentHashMap的读和写之间是没有冲突的. 换句话说, 完全可能存在脏读. 读到只写完一半的数据. 为避免出现这种情况, ConcurrentHashMap使用如volatile和代码的控制以实现原子性.

同时ConcurrentHashMap也尽量多使用了CAS, 以减少加锁次数. 但无论如何, 其效率的提升也不过是相对的.

ConcurrentHashMap第三个优化的地方是扩容. 哈希表的扩容是put操作使其元素数量达到所规定的负载因子时, 会创建一个更大的数组空间将旧数组中的所有数据搬运过去. 但问题在于, 如果数据量本身很大, 那这个搬运过程是极其耗时耗力的. 很可能出现运行卡顿.

ConcurrentHashMap所采用的也是化大为小进行搬运. 在进行扩容后,  会将新旧数组同时进行保留.每次put就将数据放到新数组中, 同时也从旧数组中搬运一部分到新数组中. 如此反复, 最后搬运结束. 这样搬运避免一次性搬运过多的数据而造成卡顿. 

-------------------------------最后编辑于2023.7.3 晚上八点半左右

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/713622.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自从前端用上了低代码,开发速度直接起飞

作为前端工作人员,我们都深知在这个快速发展的时代里,不断学习和掌握前沿技术是至关重要的。随着互联网的不断革新和新兴技术的崛起,我们需要保持敏锐的触角,紧跟潮流,才能在竞争激烈的市场中保持领先地位。 一直以来&…

MAC电脑垃圾好用的文件清理软件CleanMyMac X

古语云:“工欲善其事,必先利其器。”因此,一个运行流畅的Mac更能使我们的工作事半功倍。但又是什么导致电脑的运行不流畅呢? 其实这大多还是缓存垃圾过多、内存不足的原因。尝试安装了许多的垃圾文件清理软件,垃圾没有…

HashMap 为什么不能一边遍历一遍删除

前段时间,同事在代码中 KW 扫描的时候出现这样一条: 上面出现这样的原因是在使用 foreach 对 HashMap 进行遍历时,同时进行 put 赋值操作会有问题,异常 ConcurrentModificationException。 于是帮同简单的看了一下,印象…

为什么Qt成为工业软件开发的首选框架?

工业软件开发中使用Qt的主要原因有以下几点: 跨平台性:Qt是一个跨平台的C应用程序开发框架,可以在多个操作系统上运行,包括Windows、macOS、Linux等。这种跨平台性使得开发人员能够使用相同的代码库创建适用于不同操作系统的应用程…

Github-Readme-Stats 简明教程

注:本篇文章首发于 博客园sarexpine 为保持阅读的舒适性,可以选择移步至 博客园sarexpine 阅读,日后的文章将首发于 博客园sarexpine 平台,谢谢! 1. 更新 Readme 文件 在你想要放置 Readme-WakaTime 的位置中放置以下…

Nginx【Nginx场景实践(动静分离、动静分离实战、缓存机制)】(十)-全面详解(学习总结---从入门到深化)

目录 Nginx场景实践_动静分离 Nginx场景实践_动静分离实战 Nginx场景实践_缓存机制 Nginx场景实践_动静分离 Nginx动静分离简单来说就是把动态和静态请求分开,不能理解成只是单纯的把动态页面和静态页面物理分离。严格意义上说应该是动态请求和静态请求分开&…

@Transaction事务导致的mysql连接耗尽源码分析

背景: Transaction注解是我们在日常的写代码过程中最常使用的事务注解了,本文就从spring源码的角度解析下这个注解的执行过程,以便分析为什么使用事务比正常的单sql执行更容易导致连接池耗尽 源码追踪: 本文假定使用PROPAGATIO…

音频怎么转文字?试试这三个简单的方法吧!

有时候我们会遇到一些比较重要的会议、讲座或者演讲,如果我们能够将这些声音记录下来,并将其转换为文字,就可以更加方便地保存和管理这些信息。这样,我们就不用再去听录音了,只需要看文字就可以了。此外,录…

智能指针的deleter机制

一、介绍 智能指针的deleter机制是指,当智能指针的引用计数降为0时,智能指针会自动调用一个指定的析构函数(deleter)来释放所管理的内存。这个析构函数通常是一个函数对象,可以是一个函数指针、一个lambda表达式或者一…

青少年机器人技术一级考试备考重点(四):功与能量以及常用传动装置

随着机器人技术的飞速发展,越来越多的青少年开始关注并参与其中。青少年机器人技术考试作为一项评估学生机器人技术水平的重要考试,备受广大青少年和家长的关注。为了更好地备战青少年机器人技术一级考试,了解考试的学习要点和备考重点是非常…

C++数据结构X篇_07_C++单向循环链表解决约瑟夫问题

本篇参考单向循环链表解决约瑟夫问题(C)整理,先搞懂结构框架,后期根据视频利用c对内容实现,也可以对c有更高的提升。 文章目录 1. 链表创建与初始化2. 添加插入、删除和打印函数3. 插入数据并核验4. 解决约瑟夫问题&am…

DM8:达梦数据库备份还原报错-文件已存在 -4558 file exists

DM8:达梦数据库备份还原报错-文件已存在 -4558 file exists 1 文件已存在 -4558 file exists2 使用 OVERWRITE 参数对数据库还原3 参数介绍 1 文件已存在 -4558 file exists 在数据库还原操作时,遇到报错文件已存在 -4558 file exists,可以使用OVERWRIT…

IP归属地与IP定位

IP归属地查询是指根据给定的IP地址,确定该IP地址所属的地理位置或网络服务提供商。这种查询可以帮助用户了解到访者的地理位置,有助于网络安全、反垃圾邮件等应用。 在实际应用中,IP归属地查询常用于以下几个方面: 网络安全&…

vcruntime140_1.dll详细修复方法(推荐使用这个方法)

vcruntime140_1.dll丢失要怎么办?其实很多人都在头疼这个问题,关于dll文件的丢失这事情是时常发生的,因为电脑的杀毒软件有时候会误杀,然后就会导致你的游戏程序都打开不了,你必须要修复好了才行,今天小编就…

【UE5 Cesium】09-Cesium for Unreal 子关卡应用实例(下)

效果 通过按钮点击事件实现子关卡的切换 步骤 新建两个Actor蓝图作为GeoMarker,分别命名为“BP_GeoMarker_BeiJing”、“BP_GeoMarker_ShangHai” 分别打开这两个蓝图,添加文本渲染组件 在指定的地理位置上拖入蓝图“BP_GeoMarker_BeiJing” 控制“BP_…

分布式缓存系统热点数据

一、背景 分布式缓存一般被定义为一个数据集合,它将数据分布(或分区)于任意数目的集群节点上。集群中的一个具体节点负责缓存中的一部分数据,整体对外提供统一的访问接口 Amazon 于 2007 年提出的一种改进的一致性哈希算法 [4]。…

华为OD机试真题 Java 实现【查找单入口空闲区域】【2022 Q4 100分】,附详细解题思路

目录 一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 一、题目描述 给定一个 m x n 的矩阵,由若干字符 ‘X’ 和 ‘O’构成,’X’表示该处已被占据,’O’表示该处空闲,请找…

【JS】将表格数据下载为 .csv 文件

文章目录 代码实现 代码实现 1. 将表格数据转换为字符串格式 2. 字符串格式里面的,逗号表示换列 3. 字符串格式里面的\n符号表示换行实现 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title></head><…

Linux(包括centos) 如何查看服务器内存、CPU

CPU架构 CPU架构主要包括&#xff1a;amd64、arm32v7、arm64v8、mips64el、mips32、ppc64le和ppc32等架构。 CPU信息 CPU信息主要为中央处理器详细信息&#xff0c;包括&#xff1a; 架构核心数量处理速度厂商名称CPU主频标签 … 注&#xff1a;不同的操作系统或者CPU架构提供…

怎么提取视频中的音频?这些提取音频方法很简单

将视频中的音频提取出来&#xff0c;可以单独对音频进行处理&#xff0c;如剪辑、增强声音等&#xff0c;而不影响视频本身的内容。在后期制作中&#xff0c;音频需要经过一系列的处理&#xff0c;如去噪、降噪、混响等&#xff0c;提取出音频可以更方便地进行这些处理&#xf…