ConcurrentHashMap1.7和1.8的区别

本文详细解析了ConcurrentHashMap在Java 1.7和1.8版本中的实现原理,包括其底层结构、put和get方法的工作流程,以及从分段锁到CAS+Synchronized的并发控制策略转变。

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

ConcurrentHashMap1.7原理:

1.底层结构:数组(Segment)+ 数组(HashEntry)+ 链表(HashEntry节点)

2.ConcurrentHashMap使用了分段锁技术,当一个线程占用锁访问其中一个Segment时,不会影响访问其他Segment.

put()

1.先根据key的hash值,找到对应的Segment,在调用Segment的put()。

2.Segment的put()要加锁。(第一步先获取到锁,如果获取失败,说明有其他线程在竞争,之后自旋获取锁,自旋最多64次,到了最大次数还是没有获取锁,则改为阻塞锁获取,保证获取成功)

3.在Segment的put()中,首先先根据hash值找到头结点,如果找不到,就直接往Segment的table新增一个HashEntry,同时检查是否需要扩容;

4.如果找到了,就遍历链表,如果hash,key相等,就覆盖并且返回原值,如果找不到相等的,就直接在尾部插入一个新节点。

5.调用unlock()解除当前Segment的锁。

get()

1.get()不加锁;(HashEntry的value属性是由volatile修饰,因此保证了内存的可见性,所以取到的都是最新值,因此可以不加锁)

2.根据key的hash值,找到对应的Segment,在根据Segment的get()找到头结点,之后遍历链表,找到hash,key相等的,返回value

3.找不到头结点,或者遍历不到,就返回null。

ConcurrentHashMap1.8原理:

1.7虽然解决了并发问题,但是跟HashMap1.7一样,就是如果链表太长,会影响查询效率。因此1.8抛弃了Segment分段锁,采用CAS+Synchronized来保证并发安全性。1.8中对Synchronized 关键字进行了优化,提高了效率。

底层结构:

Node数组+链表/红黑树,和HashMap1.8类似。

put()

1.根据key得出hash值,之后判断是否需要初始化,找到头结点或者根节点,如果没有找到,就使用cas写入一个Node节点,写入失败就自旋保证成功。

2.该位置的hashcode==-1,说明需要扩容。
3.如果该位置不为空,用同步关键字加锁,那么hash>0,则是一个头结点,遍历比较,key,hash相等,覆盖返回原值,不同,尾部插入。

4.hash<0,这是一个根节点,按红黑树方式添加。

5.判断链表是否超过阈值,是否需要转化为红黑树结构。

get()

1.根据key的hash值找到位置,如果该位置为空,就返回空,如果不为空,那么hash>0,就按链表返回值,hash<0,就按红黑树返回值。

有CAS,还需要Synchronized干嘛?

cas在并发小的情况下,可以不用在用户态和内核态之间的线程上下文切换,同时自旋率降低,性能提升。但是在并发激烈的时候,自旋率激增,性能大大降低。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值