首页 > 其他分享 >谈谈ConcurrentHashMap的扩容机制

谈谈ConcurrentHashMap的扩容机制

时间:2024-11-12 10:57:23浏览次数:1  
标签:扩容 ConcurrentHashMap Java 链表 谈谈 线程 table

​ConcurrentHashMap​​​是Java中一种线程安全且高效的哈希表实现,它在Java 8之后的版本中采用了与早期版本不同的扩容机制。在Java 8及以后的版本中,​​ConcurrentHashMap​​利用了分段锁(Segment,直到Java 8)和之后的CAS(Compare and Swap)操作以及节点的树化来实现高效的并发读写和扩容,下面主要介绍Java 8及之后版本的扩容机制。

 

Java 8及以后的扩容机制概述

在Java8中,​​ConcurrentHashMap​​摒弃了分段锁的设计,转而采用更细粒度的锁,即每个桶(bin)上的链表头节点作为锁的粒度,并引入了红黑树来优化链表过长时的查找效率。其扩容过程主要包括以下几个步骤:

1.初始化新容量:当需要扩容时,会计算出新的容量,并创建一个新的、容量更大的table。扩容的触发条件通常是当元素数量超过当前容量与负载因子乘积时。

2.迁移节点:扩容的核心在于将旧table中的元素重新分配到新的table中。这个过程不是一次性完成的,而是随着每次对map的操作逐步进行。在每个桶上的链表头节点加锁的情况下,线程会遍历该链表上的所有节点,使用新的hash算法(考虑了新容量)重新计算它们在新table中的位置,并将它们移动过去。对于已经迁移到新table的节点,会设置一个 forwardingNode 标记,指示后续访问直接跳转到新table,避免重复迁移。

3.树化处理:在迁移过程中,如果发现链表长度超过了特定阈值(默认为8),会将链表转换成红黑树结构,以保持高效的查找性能。

  1. 更新大小阈值:扩容后,会根据新的容量和负载因子计算新的大小阈值,超过这个阈值才会再次触发扩容。

特点

  • 并发进行:由于采用了细粒度的锁,多个线程可以同时进行不同桶的元素迁移工作,大大提高了扩容的并发性。
  • 无锁CAS操作:在某些情况下,比如节点的简单插入或更新,会尽量使用无锁的CAS操作来减少锁的竞争,提高性能。
  • 渐进式:扩容不是一次性完成的,而是随着并发操作逐步完成,这样减少了对正常操作的影响。

总结

Java 8及之后版本的​​ConcurrentHashMap​​通过细粒度的锁、CAS操作、以及红黑树的引入,实现了高效且低阻塞的扩容机制,确保了即使在大量并发操作下也能保持良好的性能。这一设计体现了现代并发编程中追求的“无锁”或“少锁”的设计理念。

1.7版本

  1. 1.7版本的ConcurrentHashMap是基于Segment分段实现的
  2. 每个Segment相对于一个小型的HashMap
  3. 每个Segment内部会进行扩容,和HashMap的扩容逻辑类似 4.先生成新的数组,然后转移元素到新数组中
  4. 扩容的判断也是每个Segment内部单独判断的,判断是否超过阈值

1.8版本

  1. 1.8版本的ConcurrentHashMap不再基于Segment实现
  2. 当某个线程进行put时,如果发现ConcurrentHashMap正在进行扩容那么该线程一起进行扩容 3.如果某个线程put时,发现没有正在进行扩容,则将key-value添加到ConcurrentHashMap中,然后判断是否超过阈值,超过了则进行扩容
  3. ConcurrentHashMap是支持多个线程同时扩容的 5.扩容之前也先生成—个新的数组 6.在转移元素时,先将原数组分组,将每组分给不同的线程来进行元素的转移,每个线程负责一组或多组的元素转移工作

标签:扩容,ConcurrentHashMap,Java,链表,谈谈,线程,table
From: https://www.cnblogs.com/2324hh/p/18541425

相关文章

  • 谈谈零信任
    本文分享自天翼云开发者社区《谈谈零信任》,作者:姚****亮零信任本质上是以身份为中心的动态访问控制技术。其核心目标就是保障用户数据不被泄露。其理念就是认为,任何人,设备,应用都是不可信的,而传统的网络安全是假设内网是安全的,外网是不安全的,因此在内外网边界上部署防火墙,IPS,IDS,W......
  • C盘满了,C盘无损扩容,简单实现
    C盘爆满原因很多,无外乎当年固态硬盘贵,C盘分区过小,或者装系统时无意把分区分的太小,这就造成了一个困扰,C盘满了,变成红色,造成软件无法运行,电脑无法启动。如果重新分区,电脑上的资料就没了,所以今天就来介绍一款不用重装系统,扩充C盘容量的方法,操作非常简单,完全就是傻瓜式的。第一......
  • linux新增物理卷,扩容逻辑分区,出现WARNING: xfs signature detected on /dev/vdb at of
    linux新增物理卷出现WARNING:xfssignaturedetectedon/dev/vdbatoffset0.Wipeit?[y/n]:标识这个/dev/vdb磁盘已经从0位置被标记为xfs类型的文件系统报错解释:这条信息表示在设备/dev/vdb上检测到了XFS文件系统的签名。通常情况下,这可能意味着分区/dev/vdb已被......
  • 【笔记】谈谈阿里云和华为云在云原生微服务领域产品的不同之处
    背景        24年初学习了阿里云云原生微服务的课程和认证,年尾学习了华为云类似课程,想借此温故一下所学知识,结合课程内容总结谈谈对这两朵云的云原生微服务产品不同。        学习是一种愉悦,一种收获,让我们在探索中感受快乐。欢迎关注、点赞和收藏~一、谈......
  • LVM 扩容详解
    一、LVM扩容1.查看磁盘分区情况:fdisk-l  结果如下,可以看到有一块新的磁盘,需要扩容到 lvm中 2.查看pv、vg、lv情况  记录下vg名,如图,这里是centos 3.将新硬盘分区初始化pvcreate/dev/vdc(新硬盘)  可以看到如下信息即为初始化成功 4.将初始......
  • 谈谈全文检索Elasticsearch的核心概念
    Elasticsearch的核心概念1NRT(NearRealtime):近实时两方面:写入数据时,过1秒才会被搜索到,因为内部在分词、录入索引。es搜索时:搜索和分析数据需要秒级出结果。2Cluster:集群包含一个或多个启动着es实例的机器群。通常一台机器起一个es实例。同一网络下,集名一样的多个es实......
  • Java中数组“扩容”
    数组一旦创建是不能改变大小的!!!!!此处的数组"扩容"是看起来的像扩容的一种使用方式而已,不是真的改变数组大小.....可以实现,让数组用的时候感觉变大了....思路:其实创建了一个更大的数组,然后将之前数组元素拷贝大数组中,然后将大数组返回给你用。publicstaticvoidmai......
  • linux 虚拟机扩容
    虚拟机扩容是一件非常简单的事情,我们不要把他想的太麻烦了,下面我们开始操作!1.我们先用df-TH命令查看虚拟机根目录的内存通过这个命令我们发现可用的内存还有大约7G,这里一定是看根目录下的内存。2.我们先关闭虚拟机,找到编辑虚拟机设置、硬盘、扩展注意:这里的虚拟机必须......
  • 有Redis为什么还要本地缓存?谈谈你对本地缓存的理解?
    本地缓存是将数据存储在应用程序所在的本地内存中的缓存方式。既然,已经有了Redis可以实现分布式缓存了,为什么还需要本地缓存呢?接下来,我们一起来看。为什么需要本地缓存?尽管已经有Redis缓存了,但本地缓存也是非常有必要的,因为它有以下优点:速度优势:本地缓存直接利用本地内存,......
  • 虚拟机扩容ubuntu22.04磁盘空间到逻辑卷中。
    在现有磁盘基础上直接扩容的。一开始部署的时候,设置的是40GB。现在已经使用30多GB了。需要扩容下。打开虚拟机设置把磁盘扩展到一定大小root@branch-dev:~#df-hFilesystemSizeUsedAvailUse%Mountedontmpfs3.2G2.2M......