ConcurrentHashMap线程安全机制解析【个人八股】

ConcurrentHashMap 怎么保证线程安全?【重】

需要明确的是ConcurrentHashMap是hashmap的线程安全版本!

以及对应的读写操作都是怎么进行实现的!

ConcurrentHashMap 是 HashMap 的线程安全版本。

JDK 7 采用的是分段锁 ,整个 Map 会被分为若干段,每个段都可以独立加锁。不同的线程可以同时操作不同的段,从而实现并发。

JDK 8 使用了一种更加细粒度的锁------桶锁,再配合 CAS + synchronized 代码块控制并发写入,以最大程度减少锁的竞争。

对于读操作,ConcurrentHashMap 使用了 volatile 变量来保证内存可见性。

对于写操作,ConcurrentHashMap 优先使用 CAS 尝试插入,如果成功就直接返回;否则使用 synchronized 代码块进行加锁处理。

说一下 JDK 7 中 ConcurrentHashMap 的实现原理?

JDK 7 的 ConcurrentHashMap 采用的是分段锁,整个 Map 会被分为若干段,每个段都可以独立加锁,每个段类似一个 Hashtable。

每个段维护一个键值对数组 HashEntry<K, V>[] table,HashEntry 是一个单项链表。

段继承了 ReentrantLock,所以每个段都是一个可重入锁,不同的线程可以同时操作不同的段,从而实现并发。

说一下 JDK 7 中 ConcurrentHashMap 的 put 流程?

put 流程和 HashMap 非常类似,只不过是先定位到具体的段,再通过 ReentrantLock 去操作而已。一共可以分为 4 个步骤:

第一步,计算 key 的 hash,定位到段,段如果是空就先初始化;

第二步,使用 ReentrantLock 进行加锁,如果加锁失败就 自旋 ,自旋超过次数就阻塞,保证一定能获取到锁;

第三步,遍历段中的键值对 HashEntry,key 相同直接替换,key 不存在就插入。

第四步,释放锁。

说一下 JDK 7 中 ConcurrentHashMap 的 get 流程?

get 就更简单了,先计算 key 的 hash 找到段,再遍历段中的键值对,找到就直接返回 value。

get 不用加锁,因为是 value 是 volatile 的,所以线程读取 value 时不会出现可见性问题。

说一下 JDK 8 中 ConcurrentHashMap 的实现原理?

JDK 8 中的 ConcurrentHashMap 取消了分段锁,采用 CAS + synchronized 来实现更细粒度的桶锁,并且使用红黑树来优化链表以提高哈希冲突时的查询效率,性能比 JDK 7 有了很大的提升。

说一下 JDK 8 中 ConcurrentHashMap 的 put 流程?

第一步,计算 key 的 hash,以确定桶在数组中的位置。如果数组为空,采用 CAS 的方式初始化,以确保只有一个线程在初始化数组。

第二步,如果桶为空,直接 CAS 插入节点。如果 CAS 操作失败,会退化为 synchronized 代码块来插入节点。

插入的过程中会判断桶的哈希是否小于 0(f.hash >= 0),小于 0 说明是红黑树,大于等于 0 说明是链表。

第三步,如果链表长度超过 8,转换为红黑树。

第四步,在插入新节点后,会调用 addCount() 方法检查是否需要扩容。

说一下 JDK 8 中 ConcurrentHashMap 的 get 流程?

get 也是通过 key 的 hash 进行定位,如果该位置节点的哈希匹配且键相等,则直接返回值。

如果节点的哈希为负数,说明是个特殊节点,比如说如树节点或者正在迁移的节点,就调用find方法查找。

否则遍历链表查找匹配的键。如果都没找到,返回 null。

说一下 HashMap 和 ConcurrentHashMap 的区别?

HashMap 是非线程安全的,多线程环境下应该使用 ConcurrentHashMap。

相关推荐
DongQiShanRen2 小时前
六根硬件映射(四):归属澄清、两处不一致与卷十一总表
开发语言·人工智能·算法·rust·哈希算法·集成学习
DongQiShanRen13 小时前
六根硬件映射(下):物理闭环五步法,抽一条已实装的看
大数据·jvm·人工智能·算法·rust·哈希算法·集成学习
小陈不好吃1 天前
equals 与 hashCode 的契约关系:从 HashMap 到 Lombok 注解
java·hashmap·lombok
Nil2081 天前
leetcode 136只出现一次的数字
leetcode·哈希算法·散列表
余额瞒着我当琳1 天前
哈希表底层原理解析,直接定址法,哈希冲突,负载因子,哈希函数,开放定址法
java·c++·哈希算法·散列表
夕除2 天前
redis--dict rehash
算法·哈希算法
辛苦才能2 天前
C++ unordered_map/set 深度解析:快在O(1),输在无序,与map/set怎么选
c++·哈希算法·散列表
DongQiShanRen3 天前
六根硬件映射(中):双站校验、生克闭环与驱动接口
数据库·人工智能·算法·rust·哈希算法·集成学习
xuxigifxfh5 天前
牛客:BISHI8 大整数哈希
java·算法·哈希算法
code2cat5 天前
Java进阶篇之AtomicReferenceFieldUpdater:用不可变快照替换整份状态
java·开发语言·cas