2023.10.29 关于 HashTable 和 ConcurrentHashMap 区别

news2024/11/17 5:35:17

目录

HashTable

ConcurrentHashMap

优化点一

优化点二

优化点三

优化点四

不关键的小区别


HashTable

  • HashMap 和 HashTable 都是常见的哈希表数据结构,用于存储键值对

注意:

  • HashMap 是线程不安全的
  • HashTable 是线程安全的,其关键方法均加上了 synchronized,但也因此导致了性能上的开销

ConcurrentHashMap

  • 相比于 HashTable 我们更推荐使用  ConcurrentHashMap,相比于 HashTable ,其又进行了一定的线程安全优化

优化点一

  •  ConcurrentHashMap 相比于 HashTable 大大缩小了锁冲突的概率,把一把大锁转成多把小锁了
  •  HashTable 的做法是直接在方法上加 synchronized,等于是给 this 加锁,即只要操作 哈希表 上的任意元素,都会产生加锁,也就都可能发生锁冲突
  • 但是实际上,基于 哈希表 的结构特点,有些元素在进行并发操作的时候,是不会产生线程安全问题的,也就不需要使用锁控制

实例理解

  • 元素 1 、元素 2 在同一个链表上,元素 3 在另一个链表上

情况一

  • 如果此时 线程A 修改元素1,线程B 修改元素2,是否存在线程安全问题呢?
  • 可能存在
  • 比如这两个元素相邻,此时并发的插入或删除,就需要修改这俩节点相邻的节点的 next 的指向

情况二

  • 如果此时 线程A 修改元素1,线程B 修改元素3,是否存在线程安全问题?
  • 该情况相当于 多个线程 修改不同的变量,所以该情况不存在线程安全问题

  • 正是因为 HashTable ,其锁的冲突概率太大了,任何两个元素的操作都会有锁冲突,即使是在不同的链表上

  •  ConcurrentHashMap 做法是 让每个链表均有各自的锁,而不是所有链表共用同一个锁,也就是将锁的粒度变小
  • 具体来说就是使用每个链表的头结点,作为锁对象,两个线程针对同一个锁对象加锁,才有锁竞争,才有阻塞等待,针对不同的对象,没有竞争

注意:

  • 上述的 ConcurrentHashMap 是针对 JDK1.8 及以后的情况
  • 在 JDK1.7 和之前,ConcurrentHashMap 使用的是 分段锁

  • 分段锁,其本质上也是缩小锁的范围,从而降低锁冲突的概率
  • 但是这个做法并不彻底
  • 一是锁粒度分的还不够细
  • 二是代码实现也更加繁琐

优化点二

  • ConcurrentHashMap 针对读操作,不加锁,只针对写操作加锁
  • 读 和 读之间没有冲突
  • 写 和 写之间有冲突
  • 读 和 写之间也没有冲突

一般情况

  • 很多场景下,读写之间不加锁控制,可能会读到一个写了一半的结果
  • 如果写操作不是原子的,此时读就可能会读到写了一半的数据,相当于脏读

ConcurrentHashMap 优化做法

  • 使用 原子的写操作,来保证在 读写 场景下,线程读到的数据一定是完整的数据,而不是读到修改了一半的数据
  • 使用 volatile 关键字来保证及时从内存拿到修改后的数据

优化点三

  • ConcurrentHashMap 内部充分的使用了 CAS 操作
  • 以便通过 CAS 操作来进一步的削减加锁操作的数目
  • 比如维护元素个数、仅需 使用 CAS 操作进行 size++ 和 size--
  • 目的就是为了能尽可能降低锁冲突的概率,因为锁冲突对性能的影响很大

优化点四

  •  ConcurrentHashMap 针对扩容进行了优化,采取了 化整为零 的方式

HashTable 扩容方式:

  • 创建一个更大的数组空间,把旧的数组上的链表上的每个元素搬运到新的数组上(删除 + 插入)
  • 这个扩容操作会在某次 put 的时候进行触发
  • 如果元素个数特别多,就会导致这样的搬运操作,比较耗时
  • 就会出现,某次 put 比平时 put 卡很多倍(用户的感受:大部分用户用这好好的,某个用户就卡了

 ConcurrentHashMap 扩容方式:

  • ConcurrentHashMap 中,采取的是每次搬运一小部分元素的方式
  • 创建新的数组,旧的数组也保留
  • 每次 put 操作,都往新数组上添加,同时进行一部分搬运(把一小部分旧的元素搬运到新数组上)
  • 每个元素都是链表上的一个节点,其实就是 先删除旧数组上的节点 再插入到新数组的对应链表中 的操作
  • 每次 get 的时候,则 旧数组 和 新数组 一起查询
  • 每次 remove 的时候,直接删除该元素,无需搬运
  • 经过一定时间之后,所有元素都搬运好了,最终再释放旧数组 

不关键的补充

补充一

  • HashMap 的 key 允许为 null
  • ConcurrentHashMap 和 HashTable 的key 不允许为 null

补充二

  • 关于负载因子默认为 0.75
  • 但是在你的业务场景中,负载因子具体取多少,其最稳妥的办法 还是结合实际情况,选择不同的数值,进行性能测试,关注 时间 和 空间的开销,选择你认为最合适的值

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

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

相关文章

MapBox获取点位高程的三种方式

以下提供了三种方法和思路 1,通过mapbox全球dem数据获取高程 这里我们利用了mapbox的tilequery 官网地址在这里 https://docs.mapbox.com/api/maps/tilequery/ 以下是示例代码,这个方式是简单快捷,缺点就是精度不高,大概是以10m…

世界前沿技术发展报告2023《世界航空技术发展报告》(五)直升机技术

(五)直升机技术 1.常规直升机技术1.1 北约六国联合启动下一代旋翼飞行器能力项目1.2 美国和法国重视发展有人/无人直升机编组能力1.3 美国“黑鹰”直升机完成不载人全自主飞行 2.新概念直升机技术2.1 美国“劫掠者”X型直升机参与陆军“未来攻击侦察机”…

【电路笔记】-交流电感和感抗

交流电感和感抗 文章目录 交流电感和感抗1、概述1.1 电感1.2 电感器 2、频率特性2.1 电抗(Reactance)2.2 相移2.3 感应现象 3、RL滤波器4、总结 在之前有 交流电阻的文章中,我们已经看到电阻器在正常频率下的直流或交流状态下的行为是相同的。 然而,其他…

吃透进程地址空间,理清OS内存管理机制

文章目录 一、前言二、细说进程地址空间1、一段测试的代码2、引入地址空间① 富豪与他的私生子👨② 38线竟是这么来的!③ 地址空间的深层理解 三、分页 & 虚拟地址空间1、页表的概念2、疑难解答:为何父子进程没有发生同步修改&#xff1f…

注意点细节

部署esxi: VLAN 装esxi的时候如果没有设置trunk就不要设置VLAN, 否则无法访问 。 设置了trunk接口才设置VLAN,否则无法访问 部署esxi: DNS dns服务器配置: esxi 上的配置 部署ESXI :RAID 生成环境中需要先设置RAID 作为系统…

协同网络入侵检测CIDS

协同网络入侵检测CIDS 1、概念2、CIDS的分类3、解决办法4、CIDS模型5、挑战与不足 ⚠申明: 未经许可,禁止以任何形式转载,若要引用,请标注链接地址。 全文共计2598字,阅读大概需要3分钟 🌈更多学习内容&…

Spring Security授权架构介绍

授权架构重点在于从 Authentication 中获得该认证所具有的权限 GrantedAuthority,以及对请求或路径设置访问所需权限。 GrantedAuthority 在之前的Spring Security:认证架构中,我们已经介绍了在 Authentication 中存储 GrantedAuthority 的…

21. 合并两个有序链表、Leetcode的Python实现

博客主页:🏆看看是李XX还是李歘歘 🏆 🌺每天不定期分享一些包括但不限于计算机基础、算法、后端开发相关的知识点,以及职场小菜鸡的生活。🌺 💗点关注不迷路,总有一些📖知…

自相矛盾的LLM幻觉:评估、检测、缓解10.30

自相矛盾的LLM幻觉:评估、检测、缓解 摘要引言相关工作定义和激励自我矛盾4 触发、检测和减轻自相矛盾的行为5 实例化到开放文本生成6 实验 摘要 大型语言模型(Large LMs)容易产生包含虚构内容的文本。其中一个重要问题是自相矛盾&#xff0…

windows server 2016-IIS静态服务器-设置详细过程

文章目录 1.打开仪表盘新建角色2.iis功能模块3.启动服务器4.优点 1.打开仪表盘新建角色 2.iis功能模块 能选上的尽量选上,除非知道自己用不上。 然后确认,下一步,安装。 3.启动服务器 搜索IIS,启动IIS管理器。 启动网站。 右…

【杂记】Filter过滤器和Interceptor拦截器的区别

过滤器Filter与拦截器Interception区别? 包的位置不同。 filter位于tomcat里面,interception位于Spring-webmvc filter位置: interceptor位置: 实现方式不同。在自定义的时候,filter我们可以实现Filter接口&#xf…

精品Python产品销售数据可视化大屏系统-仓库出入库进销存储

《[含文档PPT源码等]精品基于Python的产品销售数据可视化系统的设计与实现》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程、包运行成功! 软件开发环境及开发工具: 开发语言:python 使用框架:Django …

组学数据上传(六)|GEO数据库数据上传实操

最近有些老师反馈文章发表时要求提供GEO登录号,如:GSEXXXX,问要怎么获取这种登录号?这时就需要把数据上传至GEO数据库了。还在等什么,跟着小编了解下GEO数据库,手把手教您上传数据至GEO数据库。 GEO数据库全称GENE EXPRESSION OMNIBUS&…

北京新一代信息技术产教联合体成立,360以ISC安全课助力建设工作

10月29日,北京新一代信息技术产教联合体(简称联合体)成立大会在北京360大厦A座报告厅成功举行。本次大会在中关村科技园区朝阳园管理委员会、北京市教委职业教育与成人教育处的指导下,由360数字安全集团、北京电子城高科技集团股份…

产品经理如何写好互联网产品说明书

互联网产品说明书是产品经理在产品开发过程中必不可少的文档之一。它起到了明确产品的功能和特性的作用,帮助团队成员更好地理解和掌握产品的核心功能。因此,作为产品经理,应该重视互联网产品说明书。那么产品经理该如何写好互联网产品说明书…

Mac电脑VS Code配置Flutter开发环境(图文超详细)

一、安装Android Studio 官网地址: https://developer.android.google.cn/ 历史版本下载地址: https://developer.android.com/studio/archive?hlzh-cn 二、安装Xcode 到App Store下载安装最新版本,如果MacOS更新不到13.0以上就无法安装…

【多线程面试题十四】、说一说synchronized的底层实现原理

文章底部有个人公众号:热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享? 踩过的坑没必要让别人在再踩,自己复盘也能加深记忆。利己利人、所谓双赢。 面试官:说一说synchronized的底…

三分钟带你了解JS、原型、原型链

1.什么是JS? JavaScript是一种基于对象的脚本语言,它不仅可以创建对象,也能使用现有的对象; 它是基于原型编程、多范式的动态脚本语言,并且支持面向对象、命令式、声明式、函数式编程范式; 白话一点说就是…

算法的时间复杂度及空间复杂度

目录 一、前言 二、时间复杂度 1.时间复杂度定义 2.时间复杂度描述方法 三、实例代码 实例1(取影响最大的项) 实例2(舍去系数) 实例3(不确定大小关系的用max函数取最大) 实例4(常数次的…

【IDEA】每个方法之间如何设置分隔线

修改后效果: 各个方法之间出现了分隔线