首页 > 其他分享 >什么是ConcurrentHashMap?不同JDK下ConcurrentHashMap的区别?

什么是ConcurrentHashMap?不同JDK下ConcurrentHashMap的区别?

时间:2024-03-07 17:35:20浏览次数:23  
标签:ConcurrentHashMap hash JDK 区别 并发 线程 数组 Segment

什么是ConcurrentHashMap?不同JDK下ConcurrentHashMap的区别?

   一、HashMap线程安全

   我们知道,在并发情况下,使用HashMap会有线程安全的问题,那么如何避免呢?

   想要避免Hashmap的线程安全问题有很多办法,比如改用HashTable或者Collections.synchronizedMap

   但是,这两者有着共同的问题:性能。无论读操作还是写操作,他们都会给整个集合加锁,导致同一时间的其他操作为之阻塞。

   在并发环境下,如何能够兼顾线程安全和运行效率呢?这时候ConcurrentHashmap就应运而生来。

    二、ConcurrentHashMap

    ConcurrentHashMap优势就是采用了[锁分段技术],每一个Segment就好比自治区,读写操作高度自治,Segment之间互不影响。

    1.  Segment

    这里面涉及到一个比较关键的概念:Segment。

    Segment本身就相当于一个HashMap对象。同HashMap一样,Segment包含一个HashEntry数组,数组中的每一个HashEntry既是一个键值对,也是一个链表的头节点。

    单一的Segment结构如下:

   

   像这样的Segment对象,在ConcurrentHashMap集合中有2的N次方个,共同保存在一个名为segments的数组当中。 

   因此整个ConcurrentHashMap的结构如下:

  

   可以说,ConcurrentHashMap是一个二级哈希表。在一个总的哈希表下面,有若干个子哈希表。

   这样的二级结构,和数据库的水平拆分有些相似。

   2. ConcurrentHashMap并发读写的几种情形

   1)Case1: 不同Segment的并发写入   

   说明:不同Segment的写入是可以并发执行的。

   2)Case2: 同一Segment的一写一读

 

   说明:同一Segment的写和读是可以并发执行的。 

   3)Case3:同一Segment的并发写入

 

  说明:Segment的写入是需要上锁的,因此对同一Segment的并发写入会被阻塞。

  由此可见,ConcurrentHashMap当中每个Segment各自持有一把锁。在保证线程安全的同时降低了锁的粒度,让并发操作效率更高。

  3. ConcurrentHashMap读写的详细过程

  1)Get方法

  •   为输入的Key做Hash运算,得到hash值。
  •   通过hash值,定位到对应的Segment对象
  •   再次通过hash值,定位到Segment当中数组的具体位置。

  2)Put方法

  •   为输入的Key做Hash运算,得到hash值。
  •   通过hash值,定位到对应的Segment对象
  •   获取可重入锁
  •   再次通过hash值,定位到Segment当中数组的具体位置。
  •   插入或覆盖HashEntry对象。

  说明:从步骤可以看出,ConcurrentHashMap在读写时都需要二次定位。首先定位到Segment,之后定位到Segment内的具体数组下标。

  4. 调用size方法时,如何解决一致性问题?

  这个问题Key理解为:既然每一个Segment都各自加锁,那么在调用Size方法的时候,怎么解决一致性的问题呢?

  分析:

 

Size方法的目的是统计ConcurrentHashMap的总元素数量, 自然需要把各个Segment内部的元素数量汇总起来。

 

 

 

但是,如果在统计Segment元素数量的过程中,已统计过的Segment瞬间插入新的元素,这时候该怎么办呢?

 

  参考资料:《程序员小灰》微信公众号

标签:ConcurrentHashMap,hash,JDK,区别,并发,线程,数组,Segment
From: https://www.cnblogs.com/hld123/p/18059376

相关文章

  • promethues 的label和metrics有什么区别:labels 用于数据监控指标的筛选,到底要监控哪
    在Prometheus中,Label和Metrics是两个核心概念,它们在监控和度量方面扮演不同的角色:Label(标签): labels用于数据监控指标的筛选,到底要监控哪些指标到promethuesLabels是用于标识和区分时间序列数据的键值对。每个时间序列数据都可以带有多个不同的标签,用来描述该数据的......
  • c#与java之间的区别盘点
    原文链接:http://www.mobiletrain.org/about/BBS/119467.htmlhttps://blog.csdn.net/clpig0125/article/details/50774628C#(CSharp)是Microsoft开发的一种面向对象的编程语言,而Java是由SunMicrosystems开发的一种面向对象的编程语言。虽然它们都是面向对象的编程语言,但它们之......
  • SD-WAN中二层组网与三层组网的区别
    前言随着企业网络需求的不断增长和变化,SD-WAN作为一种现代网络技术,为企业提供了更灵活、高效的网络解决方案。在SD-WAN中,二层组网和三层组网是两种常见的部署模型,它们有着各自的特点和适用场景。本文将深入探讨SD-WAN二层组网与三层组网的区别以及它们在不同情境下的优势。SD-WA......
  • sqlserver和mysql区别
    1.数据库管理系统SQLServer是由微软公司开发的关系型数据库管理系统,适用于Windows操作系统。而MySQL则是由瑞典MySQL公司开发的,后来被Oracle公司收购,适用于多个操作系统,包括Windows、Linux和UNIX。2.许可证和成本SQLServer是商业产品,需要购买许可证才能使用。它的价格相对......
  • Mysql和Oracle自定义函数区别
    1.Mysql自定义函数dropfunctionifexistsget_date;createfunctionget_date(v_datetimedatetime,v_timevarchar(50))returnsvarchar(50)begin declarev_datevarchar(50); declarecDatevarchar(50); declarebeginDatevarchar(50); setcDate=date_format(......
  • 不同版本jdk切换,为什么更改了系统变量也并未生效?(含解决方法)
    背景:在已经安装了jdk8的情况下,由于需要,再次又安装了jdk11,但之后想切换回jdk8时,发现即使更改了系统变量也没有生效。原因:安装jdk可以通过exe或者解压压缩包指定环境变量,详细步骤不细说。打开高级系统设置-环境变量-系统变量-path-编辑。注意:如果path对应“值”这一栏并不是以......
  • MySQL binlog/redolog/undolog 的区别?
    想和大家聊聊InnoDB中的锁机制,那么不可避免的要涉及到MySQL的日志系统,binlog、redolog、undolog等,看到有小伙伴总结的这三个日志还不错,赶紧拿来和各位小伙伴分享。日志是 mysql 数据库的重要组成部分,记录着数据库运行期间各种状态信息。mysql日志主要包括错误日志、......
  • tcp和udp的区别
    在我们的OSI七层模型或者是四层模型中,我们的传输层始终保持不变,传输层负责定义两台主机进程之间的通信,提供数据传输服务,提供端到端的可靠传输,所以我们需要用到的两个主要的协议是:TCP协议:传输控制协议,提供面向连接、可靠的数据传输服务,主要提供完整性服务UDP协议:用户数据协议,提供......
  • C#lambda与Linq区别
    相同点:都是用于查询和筛选数据的工具。异同点:**1.语法不同:Lambda是一种匿名函数,用于创建委托和表达式树;而Linq是一种查询语句,它使用特定的关键字和语法来查询数据。**2.功能不同:Lambda表达式可用于任何需要委托或表达式树的场合,而Linq语句只能用于查询和筛选数据。**3......
  • JDK1.5之后的自动装箱
    JDK1.5引入了一项非常实用的新特性,即自动装箱(Autoboxing)和自动拆箱(Unboxing)。这项特性的引入极大地简化了Java程序员在处理基本类型和它们对应的包装类之间的转换过程。自动装箱:自动装箱是指Java编译器能够在编译期间自动将基本数据类型转换为它们对应的包装类对象。例如,当你......