ConcurrentHashMap实现原理(含JDK1.7和JDK1.8对比)

本文详细介绍了JDK1.7和JDK1.8中ConcurrentHashMap的设计原理,包括分段锁和锁的粒度变化。在JDK1.7中,ConcurrentHashMap采用分段锁思想,由Segment和HashEntry数组组成;而在JDK1.8中,使用synchronized+CAS替代分段锁,提高了并发性。同时,JDK1.8引入了红黑树提高数据分布平衡性,并优化了size计算和put、get方法的实现。
摘要由CSDN通过智能技术生成

ConcurrentHashMap的前世今生

1 JDK1.7下的ConcurrentHashMap

  • 在JDK1.7之前的ConcurrentHashMap采用的是分段锁的思想,支持并发操作,所以是线程安全的。ConcurrentHashMap在内部划分成了若干个数据段(Segment),可以把每一段都大致理解成是一个HashMap。默认Segment大小为16,Segment的个数也就是锁的并发度。
  • ConcurrentHashMap是由Segment数组和HashEntry数组组成的,HashEntry数组就是HashMap中的哈希桶数组,每个Segment元素中都存储一个HashEntry数组。HashEntry数组与JDK1.7以前的HashMap中的相同,是数组+链表的结构。
  • ConcurrentHashMap对数据操作时,会对Segment段加锁(ReentrantLock ),先通过hash运算查询到数据所在的Segment段,然后对该Segment进行加锁后存储,这样就允许多个线程同时对不同Segment段的数据进行读写而不会产生线程不安全的状况,提高了并发度。
  • 统计长度时,会先不加锁统计两次,如果一样即为长度,否则加锁,重新统计。先采用不加锁的方式,连续计算元素的个数,最多计算3次:如果前后两次计算结果相同,则说明计算出来的元素个数是准确的;

2 JDK1.8下的ConcurrentHashMap

JDK1.8的HashMap中比JDK1.7多增加了一个红黑树来增加数据分布的平衡性(ConcurrentHashMap也一样)。JDK1.8的ConcurrentHashMap相对于JDK1.7,用synchronized+CAS代替了分段锁,锁的粒度变小了,并发性更大了。

  1. 锁的粒度
    JDK1.8中ConcurrentHashMap用synchronized+CAS代替了分段锁,Segment锁的粒度是Segment的个数,而JDK1.8中只会HashEntry的首节点进行加锁,所以粒度应该是下降了;
  2. 采用synchronized+CAS代替了ReentrantLock分段锁的原因
    • 分段锁中加入了Segment数组,Segment数组需要占用更多的内存空间;
    • 基于JVM的synchronized经过不断优化,性能不比ReentrantLock差,而且由于是JVM级别的,会随着JVM的优化不断被优化,提升空间比API级别的ReentrantLock更大;
  3. size实现更简单了,用Volatile修饰baseCount以记录元素的个数,当插入新数据或则删除数据时,会通过addCount()方法更新baseCount

3 JDK1.8下的put方法

  1. 初始化操作:计算hash值,定位数组下标等;
  2. 如果待插入位置没有节点元素,则通过CAS的方式,插入节点;
  3. 若当前节点Hash值为正在转移,则调用helpTransfer方法方法帮助转移,如果还在扩容,则先进行扩容;
  4. 如果发生Hash碰撞,则用synchronized关键字锁定当前节点,再进入插入(链表或红黑树插入)。
    注意:当链表长度大于等于8时,若哈希桶数组长度length<64,则不进行链表转成红黑树,而是直接进行2倍扩容

4 JDK1.8下的get方法

ConcurrentHashMap中的get方法没有加锁,因为Node属性的val和next,是用volatile修饰的,保证了可见性。
Node类:

static class Node<K,V> implements Entry<K,V> {
   
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值