浅谈ConcurrentMap的原理逻辑和hashMap及hashTable的对比分析

**

浅谈ConcurrentMap的原理逻辑和hashMap及hashTable的对比分析

**


本文不想从源码去分析底层实现的原理,都能看懂源码了,也没有必要在这儿听我聊什么蛇皮。创作目的是为了用通俗易懂的语言让初学者了解这条路的大致方向,也就是其主要的逻辑结构原理,让初学者从源码角度学习分析的时候少走弯路。

##ConcurrentMap的底层结构

ConcurrenMapt的存储是基于数组加链表,这点和hashMap、hashTable的存储原理是一样的。简单来说就是HashEntry[]数组存储元素,数组里的每个Entry元素是一个链表的形式。只不过ConcurrentMap的存储结构在此基础上多包装了一层外表,也就是segment。可以理解为分段管理。其目的是用来加锁,实现线程安全,也就是将HashEntry[]逻辑上平均分成几段,每个segment管理着HashEntry[]中的对应段的几个Entry元素。
为了帮助理解,回到hashMap及hashTable,我们知道hashMap没有锁,线程不安全,hashTable有锁,线程安全,但是hashTable一旦有一个Entry元素上锁,整个储存内容都给锁住了,无法再操作,所以效率低下,一旦死锁,整个储存内容都拉闸。所以ConcurrentMap就出现了,用segment来实现分段锁,也就是只锁要操作的部分Entry元素,能对整个存储内容的其他部分不需要上锁的Entry元素继续操作。在实现线程安全的同时大大提高了效率。

##ConcurrentMap的数据查找
我们知道hashMap的数据查找是通过数据key的hash值按位与(一个简单公式,在此略过)后算出元素在HashEntry[]中对应的位置,然后再通过equals方法比较key值在Entry链表中找到对应的值。现在的ConcurrentMap多了一层segment的外壳,如果用同样的hash算法来先确定元素在segment位置,那么到HashEntry[]这一层的时候咋办。再用同样的hash算法的话,不就会出现大量的一样的值,造成混乱。
基于此问题,ConcurrentMap在确定查询元素在segment位置的时候进行了一次在扩列,简单来说就是规定的一顿花里胡哨的操作后计算得出一个32位得hash值,然后无符号右移28位后和segmentMask进行位与操作,从而确定在那个segment的管辖范围内。(这里不用深究,对于逻辑原理不重要,就是一些简单数学计算,到时候源码看一下就行,只要知道是为了区分在HashEntry[]数组定位的区别而已),确定segment以后,接下来确定在HashEntry[]数组内的位置就和hashMap一模一样了。
##ConcurrentMap的扩容问题
所谓的扩容问题,就是我们往里面添加数据到了一定的值的时候,ConcurrentMap装不下了,只能自行扩大容量来继续存储数据。也就是接下来的两个逻辑步骤。
一、达到了扩容的条件是什么?
这就不得不提到初始化HashEntry[]的两个参数,HashEntry[]方式有四种,这里我讲最主要的,理解了,其他一看就能明白大概。这两个参数为initialCapacity(初始化容量,默认16) 和 loadFactor(负载因子,默认为0.75,通过大量测试以后,0.75的设置性能较好),实际操作过程中,想象一下应该能理解是不能等到HashEntry[]满了再进行扩容吧,因为我们存储数据并不是按顺序一个一个排序这样来存储,而是通过计算hash值来随机分配,所以空余量大的时候,基本能保证有剩余存储空间,也保障了同一个地方的数据不会太多,否则在一个地方推挤的话,各种锁数据,和大量判断排序操作等就会造成性能大大降低。
那么什么时候该扩容了呢,就也就initialCapacity*loadFactor,当 HashEntry[]存储量达到四分之三的时候,就该进行扩容了。
二、怎么扩容?
新建一个数组,数组容量为HashEntry[]的2倍,然后将当前数组内容复制进去即可。hashMap也是这样进行判断和扩容的,两者的区别就是,hashMap是先写入数据之后,然后判断是否达到扩容条件进行扩容,这样一来,如果不再往里写数据的话,扩容出的空间就被浪费掉了,而ConcurrentMap的改进在于先判断再扩容,然后在写数据,这样就不存在扩容空间的浪费问题。
##总结
主要的逻辑原理结构,上述也基本能讲清楚了,使用起来应该足够,当然还有一些细节的具体问题和怎么用,我就不细说了,有违我的创作初衷。相信你去学习的过程中,在理解我上诉内容情况下,帮助你去看源码学习能起到不错的效果。我也是一个新手小白,有什么问题和不当之处,欢迎指正和交流。希望一起学习,共同成长。
QQ:1192375101

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值