HashMap、HashTable和ConcurrentHashMap的区别

news2024/11/18 5:59:21
  1. HashMap是线程不安全的,HashTable和ConcurrentHashMap是线程安全的。

  1. HashTable的实现线程安全的方式是:将所有的方法都加上锁,也就相当于对this加锁,此时,无论访问HashTable的任何一个元素都会加锁操作,在多线程环境下出现锁冲突的概率很大。但是我们知道,基于哈希表的结构特点,有些元素在进行并发时,不会产生线程安全问题,是不需要进行加锁控制的。

  1. 而在HashTable的基础上ConcurrentHashMap 对HashTable进行了一些优化。

优化一:ConcurrentHashMap降低了锁冲突的概率,将大锁转化成多个小锁。

我们知道,HashMap的底层是由数组来完成的,每个数组元素里面都存有一个链表。

HashTable的加锁方式相当于对整个数组进行了加锁,如下图:

假如有两个线程,对1、2处进行修改操作(增删),此时可能会产生线程安全问题,需要进行加锁来保证线程安全。

但是如果是对3、4处进行修改,他们之间不会产生线程安全问题,不需要加锁进行控制,并且整体加锁还可能会产生锁冲突,进入阻塞等待,会浪费时间。

而在ConcurrentHashMap中会让每一个链表都有各自的锁,具体来说,就是将每个链表的头结点作为锁对象,当两个线程针对同一个锁对象加锁才会出现锁竞争,而针对不同对象,虽然也会上锁,但是不会有锁竞争,如下图:

针对1、2这种情况,是针对同一个对象加锁,会产生锁冲突,会保证线程安全;

针对3、4这种情况,不是针对同一个对象加锁,也就不会产生锁冲突,减少了不必要的等待时间。

上面说的优化针对jdk1.8及其以后的版本,jdk1.8以前的版本是使用分段锁的方式,如下:

这种方式没有将锁的粒度分割得足够细,并且代码的实现也更繁琐。

优化二:ConcurrentHashMap针对读操作不加锁,只针对写操作加锁

这样优化之后,加锁情况可以被分为一下几种:

读和读,不加锁

写和写,加锁

读和写,不加锁

在很多的场景下,写和读同时进行,可能会读到一个写了一半的操作,也就是脏读。

此时ConcurrentHashMap对代码进行了加volatile和将写操作进行原子性的操作,使其在读和写的情况下,也可以保持线程安全。

优化三:ConcurrentHashMap在内部充分的使用CAS

通过使用CAS,也可以进一步减少加锁操作的数量,比如维护元素个数size等

优化四:ConcurrentHashMap针对扩容,使用了“化整为零”的方式

在HashMap/HashTable中的扩容是创建一个更大的数组将旧数组上面的元素全部转移到新数组上,并且这个操作会跟随某一次put进行,如果表中的元素个数特别多。就会出现,这一次的put比平时的put卡了很多倍,很可能会影响用户的体验。

在ConcurrentHashMap中的扩容采取部分搬运的方式,它会保留新数组和旧数组

当进行put时,会将新元素放入新数组中,并且将旧数组中的一部分元素搬运到新数组中;

在进行get时,则将新旧数组都查询;

在进行remove时,只把元素删了即可。

这样经过一段时间后,旧数组里面的元素就全部都搬运倒新数组中了,此时在释放掉旧数组。

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

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

相关文章

ESP32设备驱动-MMA8451加速度计驱动

MMA8451加速度计驱动 1、MMA8451介绍 MMA8451 是一款具有 14 位分辨率的低功耗加速度计,具有灵活用户可编程选项的嵌入式功能,可配置为两个中断引脚。嵌入式中断功能可实现整体节能,从而使主机处理器免于连续轮询数据访问低通滤波数据和高通滤波数据,最大限度地减少颠簸检…

DockerCompose安装卸载、文件语法格式

DockerCompose安装卸载、文件语法格式 一、DockerCompose的概念和作用 1.1 相关概念 DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,不需要我们手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如…

【蓝桥杯】时间显示(省赛)Java

【问题描述】 小蓝要和朋友合作开发一个时间显示的网站。在服务器上,朋友已经获取了当前的时间,用一个整数表示,值为从1970年1月1日O0:00:00到当前时刻经过的毫秒数。 现在,小蓝要在客户端显示出这个时间。小蓝不用显示出年月日&a…

IIC通信协议

数据有效性 IC由两条线组成,一条双向串行数据线SDA,一条串行时钟线SCL。 SDA线上的数据必须在时钟的高电平周期保持稳定,数据线的高或低电平状态只有在 SCL 线的时钟信号是低电平时才能改变。 换言之, SCL为高电平时表示有效数据…

Crack:结构分析和设计软件:Cross Section Analysis-Design

Cross Section Analysis & Design (美国、欧洲、亚洲和澳大利亚最受好评的结构软件)是一款功能强大的应用程序,可以执行各种横截面计算,包括钢筋混凝土截面的设计(钢筋计算器)。所提供的横截面可以是简…

Python之argparse模块的使用

我们在写一个成熟的Python项目时候,需要传入若干指定的参数。而不是写死在程序里,这个时候就要用到argparse模块。argparse 是 Python 内置的一个用于命令项选项与参数解析的模块,通过在程序中定义好我们需要的参数,argparse 将会…

【FPGA笔记系列3】assign语句和if-esle语句

结构化建模 前面几节中采用的方法称为结构化建模。 assign语法(数据流建模方式) assign语句仅能描述组合逻辑电路,没有涉及时钟、触发器等! 五人投票电路(由于CGD100板子原因,需修改逻辑使按下点亮,弹起熄灭) 因为板子当key按下时为低电平,弹起时为高电平;led高电平点…

MyBatis查询接收数据 批量删除

MyBatis查询接收数据 批量删除查询出的数据只有一条通过实体类对象接收通过List集合接收通过map集合接收查询出的数据有多条通过list集合接收通过map类型的list集合接收MapKey注解模糊查询批量删除${}和#{}的区别查询出的数据只有一条 通过实体类对象接收 mapper接口代码: 映射…

Lr 12 ACR 15:传统蒙版工具

在 Lr 或 ACR 中,可以用各种不同的方式创建或添加蒙版。其中主题、天空、背景、对象及人物(若照片上有)都是由 AI 技术提供支持。画笔、线性渐变、径向渐变、范围等是传统的蒙版工具。画笔Brush手动绘制要选择的区域。创建一个画笔&#xff1…

C#,图像二值化(24)——局部阈值算法的NiBlack算法及源程序

1、局部阈值算法的NiBlack算法摘要-医学图像的处理最为复杂人和计算机。磁性捐赠的脑组织共振成像(MRI)在许多领域是非常重要的问题例如手术和治疗。最常见的分割图像的最简单方法是使用阈值。在这项工作中,我们提出了一个有效的实现阈值&…

SpringBoot整合Mybatis和MybatisPlus

目录 一、整合MyBatis操作 1、配置模式 2、注解模式 3、混合模式 二、整合 MyBatis-Plus 完成CRUD 1、什么是MyBatis-Plus 2、整合MyBatis-Plus 3、CRUD功能 一、整合MyBatis操作 官网:MyBatis GitHub SpringBoot官方的Starter:spring-boot-st…

兼容东西,贯通南北:超聚变的“四水归堂”

四水归堂,是中国建筑艺术中的一种独特形式。这种形式下,由四面房屋围出一个天井,房屋内侧坡向天井内倾斜,下雨时雨水会从东西南北四方流入天井,从而起到收集水源,防涝护屋的作用,寓意水聚天心&a…

每日一问-ChapGPT-20230114-关于小年

文章目录每日一问-ChapGPT系列起因每日一问-ChapGPT-20230114-关于小年腊月每天都做些什么的歌谣为什么现在的年味淡了很多,感觉不到过年为什么春节放假要调休,不能多放几天吗说说现在世界上极端气候,以及多少年后,地球存在不适宜…

Asp.Net项目的部署到Linux中(Linux + Jexus+Nginx )

因为老项目用的Asp.Net Web API技术开发部署到Window系统上,而新项目用的是.Net Core部署到Ubuntu系统中,所以在管理切换上有些不便。于是决定将老项目的测试服部署到Ubuntu中,试试水。 一、简述 要实现Asp.Net项目部署到Linux中&#xff0c…

C语言入门教程|| C语言 程序结构|| C语言 基本语法

在我们学习 C 语言的基本构建块之前,让我们先来看看一个最小的 C 程序结构,在接下来的章节中可以以此作为参考。 C 程序主要包括以下部分: 预处理器指令函数变量语句 & 表达式注释 让我们看一段简单的代码,可以输出单词 &qu…

Anfis-基于模糊推理的自适应神经网络程序(免费分享)

输出结果展示:完整代码:clear;close all;gamma0.75;%设定惯性因子eps10.005;%设定停止训练的条件参数m18;%设定隶属函数个数m28;a-1;b1;w0a(b-a)*rand(1,m1*m2);%初始化权值阵for i1:2switch icase 1,beta0.75;%设定学习率otherwise,beta0.25;endc[2/7*(…

ESP-IDF:链表例程实现创建,增加,打印数据成员,释放链表空间等功能

链表例程: typedef struct LISTNODE { void *data_p; LISTNODE *next; } mlistnode; typedef struct MYLIST { int size; mlistnode *head; } mylist; mylist *initial_mylist() { mylist *p (mylist *)malloc(sizeof(mylist)); p->size 0; p->head (ml…

下载指定的tomcat版本和配置

如何下载指定的tomcat版本 tomcat官网:https://archive.apache.org/ tomcat指定版本下载地址:https://archive.apache.org/dist/tomcat/ 找到指定的版本,例如这里要找到tomcat8.0.1 bin是二进制文件,src是源码文件 配置tomcat环境变量 t…

Paddle进阶实战系列(二):智慧交通预测系统

✨写在前面:强烈推荐给大家一个优秀的人工智能学习网站,内容包括人工智能基础、机器学习、深度学习神经网络等,详细介绍各部分概念及实战教程,通俗易懂,非常适合人工智能领域初学者及研究者学习。➡️点击跳转到网站。…

[ 环境搭建篇 ] 安装python环境并配置环境变量(附python3.10.3安装包)

🍬 博主介绍 👨‍🎓 博主介绍:大家好,我是 _PowerShell ,很高兴认识大家~ ✨主攻领域:【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 🎉点赞➕评论➕收藏 养成习…