面试系列Java中级:谈谈ConcurrentHashMap的原理

JDK1.7 ConcurrentHashMap主要是Segment+HashEntry分段锁实现的

结构上,ConcurrentHashMap1.7 里面包含一个Segment数组,Segment继承了ReentrantLock,Segment则包含HashEntry的数组,HashEntry本身是一个链表结构,具有保存key,value的能力并能指向下一个节点的指针。

实际上,相当于每个Segment都是一个HashMap,默认它的长度是16。也就是支持16个线程的并发读写,Segment之间互不受影响。

Put 流程

其实整个流程类似HashMap,只不过是先定位到具体的Segment,然后通过ReentrantLock去操作
1. 计算hash,定位到segment,segment如果是空就先初始化
2. 使用ReentrantLock加锁,如果获取锁失败则尝试自旋,自旋超过次数就阻塞获取,保证一定获取锁成功
3. 遍历HashEntry,就是和HashMap一样,数组中key和hash一样就直接替换,不存在就再插入链表,链表同样

Get流程 

key通过hash定位到segment,再遍历链表定位到具体的元素上,需要注意的是value是volatile的,所以get是不需要加锁的。

JDK1.8  ConcurrentHashMap主要是CAS+synchronized+Node+红黑树实现的

结构上, ConcurrentHashMap 1.8 抛弃了Segment分段锁机制,采用Node + CAS + Synchronized来保证并发安全进行实现,采用数组+链表+红黑树的存储结构。以数组元素作为锁,利用CAS+Synchronized来保证并发更新的安全,从而实现了对每个数组元素(Node)进行加锁,进一步减少并发冲突的概率。

Put流程 

1. 首先先计算hash,遍历node数组,如果node是空的话,就通过CAS+自旋的方式初始化
2. 如果当前数组位置是空则直接通过CAS自旋写入数据
3. 如果hash==MOVED,说明需要扩容,执行扩容
4. 如果都不满足,就使用synchronized写入数据,写入数据同样判断链表、红黑树,链表写入和HashMap的方式一样,key hash一样就覆盖,反之就尾插法,链表长度超过8就转换成红黑树 

Get流程 

通过key计算hash,如果key hash相同就返回,如果是红黑树按照红黑树获取,都不是就遍历链表获取。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值