多线程使用哈希表

news2025/1/31 8:00:49

❣️关注专栏: JavaEE


多线程环境使用哈希表,HashMap 本身不是线程安全的.
在多线程环境下使用哈希表可以使用:

  • Hashtable(不推荐使用)
  • ConcurrentHashMap(推荐)

🎈1 Hashtable

Hashtable是线程安全的,是给关键方法加上了关键字synchronized,等于给 this 加锁。

public synchronized V put (K key, V value) { }
public synchronized Object get (Object key) { }

这相当于直接针对 Hashtable 对象本身加锁,只要操作哈希表上的任意元素,就会产生加锁,也就可能发生锁冲突。
接下来通过图示展示 Hashtable 的加锁:
![在这里插入图片描述](https://img-blog.csdnimg.cn/eb5b979887494778ad7cba0304a61c25.png
由此可见使用HashTable锁冲突的概率太大了,任何两个元素的操作都会有锁冲突,即使是在不停的链表上。这就是不推荐使用Hashtable的最主要原因!!!
所以使用Hashtable的缺点总结有以下3点:

  • 如果多线程访问同一个 Hashtable 就会直接造成锁冲突。
  • size 属性也是通过 synchronized 来控制同步, 也是比较慢。
  • 一旦触发扩容, 就由该线程完成整个扩容过程,这个过程会涉及到大量的元素拷贝, 效率会非常低。

🎈2 ConcurrentHashMap

之所以推荐,是因为相比于 Hashtable 做出了一系列的改进和优化。 以 JDK1.8 为例。

🎈2.1 ConcurrentHashMap加锁优化

ConcurrentHashMap的加锁时对每个链表都加锁,每个链表有自己的锁,而不是所有的链表共用一个锁。加锁的方式仍然是使用 synchronized, 但是不是锁整个对象, 而是 “锁桶” (用每个链表的头结点作为锁对象), 大大降低了锁冲突的概率。
图示展示 ConcurrentHashMap加锁:
在这里插入图片描述
由此可见:使用ConcurrentHashMap,两个线程针对同一个锁对象加锁,才有锁竞争,才有阻塞等待,针对不同的对象,没有锁竞争。

🎈2.2 ConcurrentHashMap 做了一个激进的操作:针对读操作不加锁,只对写操作加锁

  • 读和读之间没有冲突;
  • 写和写之间有冲突;
  • 读和写之间也没有冲突。很多场景下读写之间没有锁控制,可能会读到一个只写了一半的结果,如果写操作不是原子的,此时就可能出现读到没写完的结果,就是“脏读”,所以针对这种情况,ConcurrentHashMap 使用了 volatile 保证从内存读取结果,从而解决了写操作不是原子的情况。

🎈2.3 充分利用 CAS 特性

ConcurrentHashMap 内部充分使用CAS,通过这个进一步的削减加锁操作,比如维护元素个数,size 属性通过 CAS 来更新, 避免出现重量级锁的情况。

🎈2.4 优化了扩容方式: 化整为零

1、HashMap/HashTable 扩容:
创建一个更大的数组空间,把旧的数组上的链表的每一个元素搬到新的数组上。这个扩容操作会在某次 put 的时候进行触发,如果元素的个数特别多,就会导致这样的搬运操作,比较耗时。就会有在某次 put 的时候比平时 put 的时候卡很多。(对于现实生活中用户的感受是:大部分用户使用的时候就会好好的,某个用户就会卡了)
2、ConcurrentHashMap 扩容:
如果有需要扩容的线程, 只需要创建一个新的数组, 同时只搬几个元素过去.。扩容期间, 新老数组同时存在,后续每个来操作 ConcurrentHashMap 的线程, 都会参与搬家的过程,每个操作负责搬运一小部分元素,搬完最后一个元素再把老数组删掉。
这个期间, 插入(每次 put)只往新数组加,同时进行一部分搬运(把一小部分旧的元素搬运到新数组);
查找(每次 get)需要同时查新数组和老数组;
每次 remove,只把元素删了就行。

🎈3 相关面试题

🎈1. ConcurrentHashMap的读是否要加锁,为什么?
不需要!读操作没有加锁.。目的是为了进一步降低锁冲突的概率。为了保证读到刚修改的数据, 搭配了volatile 关键字,可以解决不是原子的问题。
🎈 2. ConcurrentHashMap在 jdk1.8 做了哪些优化?
取消了分段锁, 直接给每个哈希桶(每个链表)分配了一个锁(就是以每个链表的头结点对象作为锁对象),图示在2.1处可见。将原来 数组 + 链表 的实现方式改进成 数组 + 链表 / 红黑树 的方式。 当链表较长的时候(>= 8 个元素)就转换成红黑树。
在JDK1.7之前都是分段锁,把若干个哈希桶分成一个"段" (Segment), 针对每个段分别加锁。 当两个线程访问的数据恰好在同一个段上的时候, 才触发锁竞争。图示如下:
在这里插入图片描述
🎈 3. Hashtable和HashMap、ConcurrentHashMap 之间的区别?
HashMap: 线程不安全, key 允许为 null。
Hashtable: 线程安全, 使用 synchronized 锁 Hashtable 对象, 效率较低, key 不允许为 null。
ConcurrentHashMap: 线程安全. 使用 synchronized 锁每个链表头结点, 锁冲突概率低, 充分利用CAS 机制, 优化了扩容方式,key 不允许为 null。
具体区别可在上述文章中看到,此处不详说。

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

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

相关文章

OpenGL中图片尺寸和上屏尺寸不一致的变形问题解决

一、尺寸不一致问题: 图片加载到OpenGL纹理,再将纹理进行上屏的时候,可能会出现图片尺寸和屏幕尺寸不一致,导致图片绘制到屏幕时出现变形的问题: 二、根本原因: 原始图片的纹理尺寸(Textur…

计网之IP协议和以太网

文章目录一. IP协议1. IPv4报头介绍2. 解决IPv4地址不够用的问题3. IP地址管理4. 路由选择二. 以太网三. 浅谈DNS域名解析系统一. IP协议 IP协议是位于OSI模型中第三层(网络层)的协议, 在这层上工作的不止这一个协议, 但IP协议是网络层传输所使用的最主流的一种协议, 有IPv4和…

C语言——指针进阶

目录 前言 一. 字符指针 二. 指针数组 三. 数组指针 3.1 何为数组指针? 3.2 &数组名与数组名 四. 数组参数、指针参数 4.1 一维数组传参 4.2 二维数组传参 4.3 一级指针传参 4.4 二级指针传参 五. 函数指针 六. 函数指针数组 七. 指向函数指针数组…

Java 继承中构造函数的问题

继承中构造函数的问题 父类构造函数和子类构造函数的关系 new一个之类对象时默认调用了父类的无参构造函数 ,创建了父类对象 父类的成员变量和成员方法才能创建出来 子类才能继承下来使用 首先创建一个父类,动物类 接下来创建一个子类,狗类&#xff…

基于OSG的虚拟校园系统的设计与实现

基于open scene graph的虚拟校园系统的设计与实现 摘要 •引言 • OSG基本原理 •OSG操作与动画 •视点的定位和切换 •自由漫游 •路径漫游 • 路径动画 • 点选和文字 • 粒子系统 • 3DMAX • 无线通信与数据库设计 • 实现步骤 • 结论 摘要 随着科技的不断发展,人工智能&a…

2023年,8种必备Selenium编写自动化用例的技巧

在开始自动化时,您可能会遇到各种可能包含在自动化代码中的方法,技术,框架和工具。有时,与提供更好的灵活性或解决问题的更好方法相比,这种多功能性导致代码更加复杂。在编写自动化代码时,重要的是我们能够…

2023年网络安全十大发展趋势

近日,中国计算机学会(CCF)计算机安全专委会中来自国家网络安全主管部门、高校、科研院所、大型央企、民营企业的委员投票评选出2023年网络安全十大发展趋势。 趋势一 数据安全治理成为数字经济的基石 我国《数据安全法》提出“建立健全数据…

spring的启动过程(一) :IOC容器的启动过程

一、web容器的加载 首先我们要先知道一个web项目的启动过程。 将Web项目部署到Tomcat中的方法之一,是部署没有封装到WAR文件中的Web项目。要使用这一方法部署未打包的webapp目录,只要把我们的项目(编译好的发布项目,非开发项目&am…

掌握MySQL分库分表(五)SpringBoot2+MybatisPlus整合Sharding-Jdbc水平分表实现

文章目录创建Java-Maven项目创建数据库、表创建Java实体类配置启动类水平分表配置文件配置测试分库分表实现分析控制台SQL逻辑SQL真实SQL主键重复问题创建Java-Maven项目 添加依赖 <properties><java.version>11</java.version><maven.compiler.source&…

PMP考试有没有什么技巧可以介绍一下么?

一、试题形式 ——中英文对照 即每道题都是一遍英文&#xff0c;一遍翻译的中文&#xff0c;在审题的时候有一些小的技巧需要注意。首先如果你的英文水平足够好&#xff0c;建议直接阅读原文。PMP试题毕竟是美国人出的&#xff0c;语言的组织、思想的表达&#xff0c;肯定更符…

python居然能语音控制电脑壁纸切换,只需60行代码

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 家在日常的电脑使用中&#xff0c;都会有自己喜爱类型的桌面 单纯的桌面有时候会让人觉得单调 今天&#xff0c;就由我带领大家只用60行代码打造一款语音壁纸切换器程序&#xff0c; 让大家能够通过语音的方式来控制电脑去…

c++模板的简单认识

文章目录 前言一.泛型编程 函数模板 模板参数的匹配原则 类模板总结前言 ADD函数很好写&#xff0c;但是如果我们要有int类型的&#xff0c;double类型的&#xff0c;char类型的等等各种类型&#xff0c;难道要写这么多不同的ADD函数吗&#xff0c;这么写简直太麻…

Linux:基于bufferevent epoll tcp服务器代码

基于bufferevent epoll tcp服务器代码: #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> #include <event2/event.h> #include <event2/buffer…

Excel/Word的一些快捷操作整理

Excel/Word的一些快捷操作整理 1. 给Word文件导入目录 前提&#xff1a;大致内容已经定稿&#xff0c;文章中各标题分级明确&#xff0c;最好各级标题字体大小设置不一样。 步骤&#xff1a;在头部导航栏&#xff0c;选择**“引用”–“目录”**&#xff0c;根据自己需求选择其…

KDJB1200六相继电保护测试仪

一、概述 KDJB1200继电保护测试仪是在参照电力部颁发的《微机型继电保护试验装置技术条件(讨论稿)》的基础上&#xff0c;广泛听取用户意见&#xff0c;总结目前国内同类产品优缺点&#xff0c;充分使用现代新的的微电子技术和器件实现的一种新型小型化微机继电保护测试仪。可…

DataWhale 大数据处理技术组队学习task3

四、分布式数据库HBase 1. 产生背景 1.1 Hadoop的局限性 优点&#xff1a;存储结构化、半结构甚至非结构化的数据&#xff0c;是传统数据库的补充&#xff0c;是海量数据存储的最佳方法。缺陷&#xff1a; 只能进行批处理&#xff0c;并且只能以顺序的方式访问数据。&#x…

【C++】-- 异常

目录 C语言传统的处理错误的方式 C异常概念 异常的使用 异常的抛出和捕获 自定义异常体系 异常的重新抛出 异常安全 异常规范&#xff08;C期望&#xff09; C标准库的异常体系 异常的优缺点 C异常的优点 C异常的缺点 总结 C语言传统的处理错误的方式 传统的错误…

zookeeper单机部署

一.下载zookeeper压缩包 二.上传解压安装包到/data/zookeeper目录&#xff0c;并解压 tar -zxvf apache-zookeeper-3.5.8-bin.tar.gz 三.修改配置文件 cd apache-zookeeper-3.5.10-bin/conf mv zoo_sample.cfg zoo.cfg vi zoo.cfg 修改为如下&#xff1a; dataDir/data/zooke…

【研究空间复用及函数调用问题】

本篇总结函数调用过程会存在的一些奇怪现象&#xff0c;空间复用问题&#xff0c;其实本质上涉及函数调用的底层原理&#xff0c;理解函数栈帧的创建和销毁这样的问题直接迎刃而解。1.空间复用问题案例1案例22.函数调用过程不清晰问题案例33.总结1.空间复用问题 案例1 我们先…

程职场人必备微软出品的实用小工具

系统增强工具PowerToys 下载地址&#xff1a;https://github.com/microsoft/PowerToys 什么是 Windows 系统中&#xff0c;最好的辅助工具&#xff1f; PowerToys 一定可以获得提名。PowerToys 是一款来自微软的系统增强工具&#xff0c;就像是一个神奇的系统外挂&#xff0c;…