当前位置: 首页> 娱乐> 影视 > ConcurrentHashMap解析

ConcurrentHashMap解析

时间:2025/7/15 21:31:10来源:https://blog.csdn.net/m0_74107946/article/details/141785081 浏览次数:0次

ConcurrentHashMap的结构

在这里插入图片描述

  • 实现了AbstractMap
  • 核心是有一个Segments的属性,这个属性相当于一个重入锁ReentrantLock,是一个数组加链表的结构,每个HashEntry数组进行修改时,必须获得它对应的Segment锁
  • 接着看表中Segments的属性中有一个HashEntry->这个是一个链表节点,用于存储数据,指向下一个节点(讲大数据分成几段数据,然后变成segment,每段数据当中又被分成多个数组)

初始化

通过三个属性:initCapcity ,concurrencyLevel,loadFactor
initCapcity
这个属性决定了ConcurrentHashMap的总初始容量,和之后的segment相关
concurrencyLevel
默认16,决定了segment的数量,最多支持16个线程并发写,一旦初始化,就不能再扩容
loadFactor
Segment中的哈希表使用的,refresh——>对哈希表(底层是数组)扩容

使用new ConcurrentHashMap()进行无参构造

  • 初始化容量Segment数组长度是16,不可以扩容
  • segment[i]的初始容量为2,loadFactor = 0.75

定位Segment

可以类比之前的HashMap,也是需要定位元素的
数据需要收到Segment分段锁保护,所以插入或者获取元素的时候,必须先定位到Segment
源代码
这个上面的就是源代码进行再散列,目的是减少散列冲突,使元素能够减少散列冲突,使元素均匀地分布在不同的Segment上,从而提高容器的存取效率。
在这里插入图片描述

get操作

在这里插入图片描述
先进行一次再散列,然后使用这个散列通过散列运算定位到Segment,再通过散列算法定位到元素。

get操作的高效之处在于这个get过程不需要加锁

put操作

这个必须加锁(写入)
在Segment里进行插入操作,插入操作需要经历两个步骤:

  • 是否需要扩容:在插入元素前会先判断Segment的HashEntry数组是否超过容量**(threshold)**,如果超出阈值,需要对数组进行扩容。Segment的扩容判断比HashMap更恰当
  • 定位添加元素的位置,然后将其放在HashEntry数组中。

size操作

连续不加锁累加2次,如果期间都发生了变化,再加锁:
使用modCount这个中间变量,对于添加,删除,修改这些操作都对modCount进行加1.

JDK 1.8ConccurrentHashmap实现原理

数组+链表 ->数组+链表+红黑树,加锁采用CAS和synchronized

get 方法

在这里插入图片描述

  • 计算Hash值,并由此找到槽点
  • 如果数组是空->返回null
  • 如果该位置节点是我们需要的,直接返回该节点的值
  • 如果改位置节点是红黑树或正在扩容,直接使用find继续查找
  • 否则就是链表,进行遍历链表查找
关键字:ConcurrentHashMap解析

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: