【JavaEE】ConcurrentHashMap与Hashtable有什么区别?

news2024/11/21 2:37:00

  • 博主简介:努力的打工人一枚
  • 博主主页:@xyk:
  • 所属专栏: JavaEE初阶

Hashtable、ConcurrentHashMap是使用频率较高的数据结构,它们都是以key-value的形式来存储数据,且都实现了Map接口,日常开发中很多人对其二者之间的区别并没有十分清晰的概念。 


目录

一、多线程环境使用哈希表

1.1什么是Hashtable?

1.2什么是ConcurrentHashMap?

二、ConcurrentHashMap的改进

三、ConcurrentHashMap和Hashtable的区别

3.1 加锁粒度的不同

3.2更充分的利用了CAS机制

3.3优化了扩容策略

四、相关面试题

4.1 ConcurrentHashMap的读是否要加锁,为什么?

4.2 介绍下 ConcurrentHashMap的锁分段技术?

4.3 ConcurrentHashMap在jdk1.8做了哪些优化?

4.4 Hashtable和HashMap、ConcurrentHashMap 之间的区别?


一、多线程环境使用哈希表

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

  1. Hashtable
  2. ConcurrentHashMap

1.1什么是Hashtable?

本篇不再详细介绍,想要了解详细请点击:Hashtable是什么?它和Hashmap有什么区别?_xyk:的博客-CSDN博客

只是简单的把关键方法加上了synchronized关键字

 

 加到方法上,相当于是针对this加锁了

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

1.2什么是ConcurrentHashMap?

 

ConcurrentHashMap底层是基于数组+链表,jdk1.7中的数据结构采用分段式设计,segment数组 + HashEntry数组 + 链表实现,hash冲突采用拉链法处理。

而在jdk1.8中,借鉴了jdk1.8中HashMap的设计思想,采用数组 + 链表 + 红黑树的数据结构,并且有原来的分段式锁换成了CAS + Synchronized锁,使用的是尾插法,其它的地方并没有改变。

二、ConcurrentHashMap的改进

相比于 Hashtable 做出了一系列的改进和优化. 以 Java1.8 为例;

  1. 读操作没有加锁(但是使用了 volatile 保证从内存读取结果), 只对写操作进行加锁. 加锁的方式仍然是是用 synchronized, 但是不是锁整个对象, 而是 "锁桶" (用每个链表的头结点作为锁对象), 大大降低了锁冲突的概率
  2. 充分利用 CAS 特性,比如 size 属性通过 CAS 来更新,避免出现重量级锁的情况.
  3. 优化了扩容方式:化整为零
  4. ConcurrentHashMap不允许key或value为null值

三、ConcurrentHashMap和Hashtable的区别

3.1 加锁粒度的不同

Hashtable是针对整个哈希表加锁,任何的增删改查操作,都会触发加锁,也就可能会有锁竞争!!实际上仔细思考,其实没必要把锁加的这么勤快

插入元素:

根据key计算hash值 ->数组下标,把这个新的元素给挂到对应的下标的链表上,那么如果是俩个线程,插入俩个元素,虽然俩个操作没有线程安全问题,但是由于synchronized是加到this上,仍然会针对同一个对象产生锁竞争,产生阻塞等待!!!

 

那么如果是ConcurrentHashMap不是只有一把锁了,每个链表的头节点都作为一把锁~~

每次进行操作,都是针对对应链表的锁进行加锁,那么操作不同的链表就是针对不同的锁加锁,不会有锁冲突;

导致大部分加锁操作实际上没有所冲突的!!此时加锁操作的开销就微乎其微了~~~

上述内容是ConcurrentHashMap和Hashtable之间最大,最关键的,最核心的区别

伪码:

void put(String key,String value){
//先找到对应的链表的头节点
 int index = hashCode(key); 
 Node head = getHead(index);
 synchronized(head){
   执行链表进行插入节点操作
 }
}

3.2更充分的利用了CAS机制

更充分的利用了CAS机制——无锁编程;有的操作,比如获取/更新元素个数,就可以直接使用CAS完成,不必加锁了。CAS也能保证线程安全,往往比锁更高效。

3.3优化了扩容策略

对于Hashtable来说,如果元素太多了,就会涉及扩容;扩容需要重新申请内存空间,搬运元素(把元素从旧的哈希表上删掉,插入到新的哈希表上)如果本身元素非常多,上亿个,全部搬运一次,成本就很高,就会导致这一次put操作效率很低,非常卡顿!!

那么ConcurrentHashMap策略,化整为零;并不会试图一次性的就把所有元素都搬运过去,而是每次就搬运一部分;当put触发扩容,此时就会直接创建更大的内存空间,但是并不会直接把所有元素都搬运过去,而是只搬运一小部分,速度还是比较快的;

此时,相当于存在俩份hash表了,如果要插入元素,直接往新表拆入;删除元素,删除旧表,或元素在哪个表就删除哪里;查找,新表旧表都查找!!并且每次操作过程中,都搬运一小部分元素过去~~~

四、相关面试题

4.1 ConcurrentHashMap的读是否要加锁,为什么?

读操作没有加锁. 目的是为了进一步降低锁冲突的概率. 为了保证读到刚修改的数据, 搭配了
volatile 关键字

4.2 介绍下 ConcurrentHashMap的锁分段技术?

这个是 Java1.7 中采取的技术. Java1.8 中已经不再使用了. 简单的说就是把若干个哈希桶分成一个"段" (Segment), 针对每个段分别加锁.
目的也是为了降低锁竞争的概率. 当两个线程访问的数据恰好在同一个段上的时候, 才触发锁竞争

4.3 ConcurrentHashMap在jdk1.8做了哪些优化?

取消了分段锁, 直接给每个哈希桶(每个链表)分配了一个锁(就是以每个链表的头结点对象作为锁对象).
将原来 数组 + 链表 的实现方式改进成 数组 + 链表 / 红黑树 的方式. 当链表较长的时候(大于等于8 个元素)就转换成红黑树

4.4 Hashtable和HashMap、ConcurrentHashMap 之间的区别?

  • HashMap: 线程不安全. key 允许为 null
  • Hashtable: 线程安全. 使用 synchronized 锁 Hashtable 对象, 效率较低. key 不允许为 null
  • ConcurrentHashMap: 线程安全,使用 synchronized 锁每个链表头结点,锁冲突概率低, 充分利用CAS 机制,优化了扩容方式,key 不允许为 null

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

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

相关文章

Jmeter实验

Jmeter实验 启动Jmeter 点击bin目录下的,jmeter进行启动 修改界面语言为中文 发起一个最基本的请求 线程组,Http请求,察看结果树 察看结果树的作用范围 设置请求跟随重定向 响应断言-响应文本 判断响应文本中是否有"百度一…

Scala大数据开发

版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl Scala简述 在此,简要介绍 Scala 的基本信息和情况。 Scala释义 Scala 源自于英语单词scalable,表示可伸缩的、可扩展的含义。 Scala作者 Scala编…

UDS介绍

首先要有网络网络七层的概念: 学习链接: 七层网络模型-CSDN博客 UDS网络层/TP层(ISO 15765-2)的解读 - 知乎 (zhihu.com) 概念: UDS(Unified Diagnostic Services,统一的诊断服务。 标准名是《…

【栈和队列高频考点题】

目录 1 与栈有关的考题 1.1 最小栈 1.2 栈的弹出压入序列 1.3 逆波兰表达式求值 1.4 二叉树的最近公共祖先 1.5 单调栈 2 与队列有关的考题 2.1 二叉树的分层遍历 2.2 滑动窗口 1 与栈有关的考题 1.1 最小栈 题目描述: 解题思路: 要想在O(1…

微信小程序引入 vant ui组件

1.初始化 在小程序根目录(app.js所在目录),打开cmd命令窗口 npm init -y参数 -y 表示对 npm 要求提供的信息,都自动按下回车键,表示接受默认值。 2.下载miniprogram依赖 通过 npm 安装: npm i vant/weapp -S --p…

京东开源RaftKeeper性能超越ZooKeeper!

一、背景介绍 成百上千台服务器组成的分布式系统中,服务器故障或网络抖动会随时发生,有时会导致严重的系统崩溃,为解决如上问题,雅虎开源了ZooKeeper分布式协调服务并在2010年成为Apache顶级项目,是Hadoop、HBase和Cl…

为什么FTP会随着时间的过去而变慢?

有人问:我在XP上有FZ客户端3.5.3,在Vista上有0.9.41服务器。通过已经很慢的连接传输大文件时,我注意到速度开始时约为40kb / s,但逐渐趋于稳定,约为20kb / s,并保持这种状态。如果我退出客户端并重新启动它…

夜天之书 #81 大厂开源之殇

本轮开源之风吹起迄今数年,最大的影响还是越来越多的商业公司开始探索开源方法能够如何改变自己的经营策略。开源策略循序渐进分成使用、参与和发起。在发起开源项目实践一线的,一个是打着开源旗号的创业公司,另一个就是大型企业尤其互联网企…

JUC并发编程之AQS原理

1. AQS 原理 1.1 概述 全称是 AbstractQueuedSynchronizer,是阻塞式锁和相关的同步器工具的框架 特点: 用 state 属性来表示资源的状态(分独占模式和共享模式),子类需要定义如何维护这个生态,控制如何获…

剪枝与重参第六课:基于VGG的模型剪枝实战

目录基于VGG的模型剪枝实战前言1.Intro2.Prune实战2.1 说明2.2 test()2.3 加载稀疏训练模型2.4 前处理2.5 建立新模型并存储信息2.6 BatchNorm层的剪枝2.7 Conv2d的剪枝2.8 Linear的剪枝3.基于VGG的模型剪枝总结基于VGG的模型剪枝实战 前言 手写AI推出的全新模型剪枝与重参课程…

快排的递归实现

快速排序是一种时间复杂度低,但会虽随着数组的顺序变化,因为其效率之高被称为快速排序,而 且其不稳定性也可以同过优化进行解决。 快速排序的实现有三种方法: 1.hoare版 其基本思想为:任取待排序元素序列中 的某元…

3、如何使用GDB来进行命令行debug

文章目录一、与前面的联系二、GDB的一些认识1、什么是gdb2、gdb作用3、gdb可实现的功能三、GDB常用的调试命令一、与前面的联系 对于前面说到的launch.json文件就是用于debug的配置文件,在前面的vscode中我们可以发现配置好launch.json文件之后进行调试&#xff0c…

攻防世界-web2(逆向加密算法)

打开链接是PHP源码 给了一串密文,并对这串密文进行了一系列操作加密,注释里说解密$miwen就是flag 在此我们先介绍一些PHP内置函数: strrev(string): 反转字符串 strlen(string): 返回字符串的长度 substr(string, start, length): 返回字符…

认识、使用C++vetor和array

目录 前言: 1.vector模板 1.1vector简介 1.2创建vector类对象 2.array模板 2.1array简介 2.2创建array类对象 3.比较中学习 4.怎么避免数组越界访问 前言: 指针的基础用法分了近三篇文章,结合数组、结构、共用体、字符串一起学习。相…

【Golang | http】使用http库完成一个简单的POST请求

引言 主要记录使用Golang实现一个POST请求所用到的小知识点 1、项目结构 客户端向服务端注册用户信息,服务端返回注册信息中的用户名 PS E:\goland-workspace\GolangLearning\http> tree /f 卷 文件 的文件夹 PATH 列表 卷序列号为 0C66-1433 E:. ├─client…

小样本学习FSL介绍

1 概念 小样本学习(few-shot learning,FSL)旨在从有限的标记实例(通常只有几个)中学习,并对新的、未见过的实例进行识别。 相比于传统的深度学习和机器学习方法,小样本学习能够更好地模拟人类的…

从C出发 22 --- 变量的作用域与生命期

问题 1 : 这样子定义一个不属于任何函数的变量正确吗? 问题 2 : 编译能通过吗? 问题 : 我们要打印的var 到底是 10 还是 100. 总结: 什么都不会输出,因为这里的 i ;是让局部变量的 i ,程序会一直死循环 为什么都是 11,为什…

在构建个人想法时,使用哪个工具更好呢?Tana, AmpleNote 和 妙记多 Mojidoc的比较

笔记类 App 都很强调个人化,因为我们每个人会用不同的方法来做笔记、写日记。不过有一些框架可以帮助我们,比如子弹笔记(Bullet Journal)等。 Tana 和 Amplenote 都可以使用「标签」,尽管它们处理的方式、体验都大不相…

4.14~4.16学习总结

多线程: 同步代码块 格式:Synchronized(锁) { 操作共享数据的代码 } 特点1:锁默认打开,有一个线程进去了,锁自动关闭。 特点2:里面的代码全部执行完毕,线程处理,锁自动打开。 …

SaleSmartly(ss客服)怎么玩转Instagram自动化?

这段时间接触了不少粉丝,一直在说ins营销,说谁谁谁通过这个引流,结果爆了,那我们今天就来简单说一下。Instagram (IG) 是全球最大的照片和视频共享平台,拥有超过10亿的月活跃用户和 5 亿的日活跃Story用户。借助IG的强…