ConcurrentHashMap1.7 和 1.8的区别

一、ConcurrentHashMap 1.7 

1、数据结构:

Segment数组 + 多个HashEntry组成、Segment数组又是由多个Segment元素组成,每个Segment元素又是由一个HashEntry数组和链表组成;

2、put操作

  • 第一次计算key的hash,找到Segment元素的位置;
  • 判断当前Segment元素是否初始化,若没有初始化,则通过CAS进行初始化;
  • 第二次计算key的hash,找到HashEntry数组的位置;
  • 由于Segment继承了ReentrantLock锁,所以TryLock() 尝试获取锁,如果锁过去成功,将数据插入到HashEntry位置,如果遇到Hash冲突,则插入到链表的末端;如果锁被其他线程获取,那么就会以自旋的方式重新获取锁,超过指定的次数之后还获取不到的话,就会挂起,等待唤醒;

3、get操作

  • 第一次计算key的hash,找到Segment元素的位置;
  • 第二次计算key的hash,找到HashEntry数组的位置;
  • 遍历链表,匹配就返回,否则返回null;

4、size操作(两种方式)

  1. 采用不加锁的方式,多次计算count,(最多三次),比较结果,如果相同的话,就准备,否则的话计算的结果不准确;
  2. 采用加锁的方式,给所有Segment元素加锁,计算出count值,这个是准确的;

二、ConcurrentHashMap 1.8

1、数据结构

Node数组 + 链表 + 红黑树,并发操作使用的是Synchronized和CAS来控制;

2、put操作

  • 如果没有初始化就先调用initTable()方法来进行初始化过程;
  • 如果没有hash冲突就直接CAS插入;
  • 如果还在进行扩容操作就先进行扩容;
  • 如果存在hash冲突,就加锁来保证线程安全,这里有两种情况,一种是链表形式就直接遍历到尾端插入,一种是红黑树就按照红黑树结构插入;
  • 最后一个如果该链表的数量大于阈值8,就要先转换成黑红树的结构,break再一次进入循环;
  • 如果添加成功就调用addCount()方法统计size,并且检查是否需要扩容;

3、get操作

  • 计算hash值,定位到该table索引位置,如果是首节点符合就返回;
  • 如果遇到扩容的时候,会调用标志正在扩容节点ForwardingNode的find方法,查找该节点,匹配就返回;
  • 以上都不符合的话,就往下遍历节点,匹配就返回,否则最后就返回null;

4、size操作

直接返回count

 

总结:

ConcurrentHashMap 1.7  Segment + HashEntry + ReentrantLock       锁粒度为Segment

ConcurrentHashMap 1.8 HashEntry + synchronized + CAS + 红黑树  锁粒度为HashEntry

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值