ConcurrentHashMap原理解析

ConcurrentHashMap原理解析

【什么是ConcurrentHashMap?】
众所周知,Hashmap是一种非常高效的数据结构,但是依旧有它的缺陷。那就是在并发插入数据时,有可能会出现带环链表,让下一次的读操作出现死循环。于是为了避免HashMap的线程安全问题,ConcurrentHashMap应运而生。

【ConcurrentHashMap原理】
ConcurrentHashMap是一个二级hash表,在一个总的hash表下面有若干子hash表。
我们将子hash表称为Segment。
那么采用这种结构有什么好处呢?
我们知道解决线程安全问题的方法,就是加锁。当时给整体加锁的话,又会使得效率急剧下降。在ConcurrentHashMap的结构下我们就可以采用【锁分段技术】,每个Segment就是一个自治区,读写操作高度自治,Segment间互不影响。
ConcurrentHashMap解决线程安全问题的具体场景:
场景1:不同Segment的读与读,读与写,写与写
可以并发执行
场景2:同一Segment的写与读
可以并发执行
场景3:同一Segment的并发写入
加锁
因此,采用给单个的Segment加锁,相比于整体加锁就极大地提高了效率,同时保证了线程安全。

【ConcurrentHash方法】
【get方法】

  1. 为输入的key值,进行hash运算得到hash值
  2. 通过hash值定位到对应的Segment
  3. 再次通过hash值,定位到Segment中的对应位置

【put方法】

  1. 为输入的key值,进行hash运算得到hash值
  2. 通过hash值定位到对应的Segment
  3. 为当前Segment加可重入锁
  4. 进入Segment找到对应位置,进行插入或者覆盖
  5. 释放可重入锁

【size方法】
在ConcurrentHashmap的size方法中采用了乐观锁与悲观锁相结合的方式。
正常来说,我们统计size时,直接获取各个Segment的子元素的个数之和即可。
当若是当我们刚刚计算结束某一Segment的元素之后,该Segment又进行了插入或者移除操作怎么办呢?
具体实现流程如下:

  1. 获取当前ConcurrentHashmap的修改次数version
  2. 遍历所有Sgement,获得子元素数量之和
  3. 再次获取当前ConcurrentHashmap的修改次数version
  4. 对比两次version,如果第二次大于第一次,说明统计过程中有修改,重新统计,尝试次数+1;若二者相同,说明没有修改,统计结束。
  5. 如果尝试次数超过阈值,则对每一个Segment加锁,再重新统计。
  6. 再次判断所有Segment的总修改次数是否大于上一次的总修改次数。由于已经加锁,次数一定和上次相等。
  7. 释放锁,统计结束

学习参考来源:小灰大神

【补充内容】
乐观锁与悲观锁的相关内容,在下一篇博客会更新

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

喜鹊先生Richard

随缘~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值