ConcurrentHashMap 实现原理与使用

一、ConcurrentHashMap

ConcurrentHashMap 采用锁分段技术有效提高了并发访问率,首先将数据分成一段一段地存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问;

1. ConcurrentHashMap 的结构

ConcurrentHashMap 由 Segment 数组结构 和 HashEntry 数组结构组成,一个ConcurrentHashMap 里面包含一个 Segment 数组(数组链表结构),一个 Segment 里面包含一个 HashEntry 数组 (链表结构),每个 Segment 守护一个HashEntry 数组里的元素,当对 HashEntry 数组的数据进行修改时,必须首先获得它对应的 Segment 锁
在这里插入图片描述

2. ConcurrentHashMap 的初始化

通过 initialCapacity 、loadFactor 、concurrentLevel 等几个参数来初始化segment 数组,段偏移量 segmentShift 、段掩码 segmentMask 和每个 segment 里的 HashEntry 数组;

初始化参数作用默认值最大值
initialCapacity是ConcurrentHsahMap 的初始化参数16
loadFactor是每个 segment 的负载因子0.75
concurrencyLevel16
segmentShift用于定位参与散列运算16
segmentMask散列运算的掩码65535
3. 定位Segment

在使用分段锁时,插入和获取元素都必须先通过散列算法来定位到 Segment ,首先使用 Wang/Jenkins hash 的变种算法对元素的 hashcode 进行一次再散列,其目的时减少散列冲突,使元素能够均匀的分布在不同的 Segment 上,从而提高容器的存取率;

4. ConcurrentHashMap 的操作
(1)get 操作

先经过一次再散列,然后使用这个散列值通过散列运算定位到 Segment ,再通过散列算法定位到元素,整个 get 过程不需要加锁,除非读到的值为空猜会加锁重读,所以该操作很高效;

(2)put 操作

该操作首先定位到 Segment 然后再 Segment 里进行插入操作,插入时先判断 Segment 里的 HashEntry 数组是否需要扩容,如果超所阈值,再扩充为原来的两倍,然后定位添加的元素的位置,然后放入 HashEntry 数组里;

(3)size 操作

想要统计ConcuurentHashMap 里元素大小,先尝试 2 次通过不锁住 Segment 的方法来统计各个 Segment 大小,如果统计过程中,容器的 count 发生了变化,则在采用加锁的方式来统计所有 Segment 的大小;

### ConcurrentHashMap 实现原理 #### 数据结构 ConcurrentHashMap 在 JDK 8 中采用了 `Node` 数组加链表和红黑树的方式来存储键值对。当哈希冲突发生时,会形成一条链表;如果链表长度超过一定阈值,则转换为红黑树以提高查找效率[^1]。 #### 并发控制机制 为了提升性能并减少锁竞争,ConcurrentHashMap 将整个映射分割成多个部分(称为段),通过调整并发级别参数可以改变这些段的数量,默认情况下有 16 个这样的段。每个段都相当于一个小的独立哈希表,并且拥有自己的锁对象。因此,在多线程环境下操作不同段的数据不会引起相互之间的阻塞等待现象,从而提高了整体吞吐量[^2]。 #### 原子更新操作 内部大量运用了无锁编程中的 CAS (Compare And Swap) 技术来进行高效的原子化修改动作,比如插入新节点或者替换已有条目等。CAS 是一种乐观锁定策略,它允许程序尝试执行某些变更而无需持有任何显式的互斥锁资源,只有当检测到预期条件满足时才会真正提交更改请求。 ```java // 示例代码展示如何使用 ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap; public class Example { private static final int CAPACITY = 1 << 4; public static void main(String[] args){ var map = new ConcurrentHashMap<String, String>(CAPACITY); // 插入数据项 map.put("key", "value"); // 获取指定 key 对应 value System.out.println(map.get("key")); } } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值