ConcurrentHashMap底层结构(JDK1.7)

本文详细介绍了ConcurrentHashMap在JDK1.7中的实现原理,包括其线程安全的分段锁策略,以及如何通过Segment和HashEntry数组实现高效并发访问。在查找和插入操作中,ConcurrentHashMap避免了全锁同步,提供了更高的并发性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

HashMap不是线程安全的,HashTable虽然是线程安全,但是该类所有的方法都用synchronized进行线程安全的控制,在高并发的情况下,同一时刻只有一个线程可以获取对象监视器,其他线程阻塞或者轮询等待,在线程竞争激烈的情况下,这种方式的效率会非常的低下。

 

HashTable在扩容的时候,newSize = 2 * oldSize + 1;

 

ConcurrentHashMap是线程安全的,使用了锁分段的思想提高了并发度。

ConcurrentHashMap为什么高效:

Hashtable低效主要是因为所有访问Hashtable的线程都争夺一把锁。如果容器有很多把锁,每一把锁控制容器中的一部分数据,那么当多个线程访问容器里的不同部分的数据时,线程之前就不会存在锁的竞争,这样就可以有效的提高并发的访问效率。这也正是ConcurrentHashMap使用的分段锁技术。将ConcurrentHashMap容器的数据分段存储,每一段数据分配一个Segment(锁),当线程占用其中一个Segment时,其他线程可正常访问其他段数据。

 

jdk1.7下ConcurrentHashMap的数据结构:

image

ConcurrentHashMap包含一个Segment数组,每个Segment包含一个HashEntry数组,当修改HashEntry数组采用开链法处理冲突,所以它的每个HashEntry元素又是链表结构的元素。

查找元素时,先通过key定位到Segment的下标位置,再找到对应的HashEntry的下标位置,然后再比较key的值。

Segment是ConcurrentHashMap的一个内部类,主要组成如下:

HashEnrty源码:

 

 

和HashMap非常类似,唯一的区别是核心的数据如value,以及链表都是volatile修饰的,保证了获取时的可见性。

原理上来说,ConcurrentHashMap采用了分段锁的技术,不会像HashTable那样不管put和get都需要同步处理,

理论上ConcurrentHashMap支持Segment数组数量大小的线程并发,当一个线程占用锁访问Segment时不会影

响到其他的Segment。

put()方法:

首先通过key定位到Segment

 

在具体的Segment再进行put,首先第一步的时候会尝试获取锁,如果获取失败肯定就有其他线程存在竞争,则利用

scanAndLockForPut()自旋获取锁:

1.尝试自旋获取锁

2.如果重试次数达到了MAX_SCAN_RETRIES则改为阻塞锁获取成功,保证能获取成功

get()方法:

 

get的逻辑比较简单,key通过hash之后定位到具体的Segment,

再通过一次 Hash 定位到具体的元素上。

由于 HashEntry 中的 value 属性是用 volatile 关键词修饰的,保证了内存可见性,所以每次获取时都是最新值。

ConcurrentHashMap 的 get 方法是非常高效的,因为整个过程都不需要加锁

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值