ConcurrentHashMap底层实现是什么

ConcurrentHashMap整体结构

        ConcurrentHashMap是一个K-V的存储结构,在JDK1.8中,它的存储结构如下,是由数组、单向链表、红黑树组成。当我们初始化一个实例时,默认会初始化一个长度为16的数组。由于ConcurrentHashMap本质上还是一个hash表,所以key会存在hash冲突,它采用链式寻址法来解决hash冲突。当hash冲突比较多时,会使链表长度过长,因此查询的复杂度就增加。因此JDK1.8中引入了红黑树的算法,当数组长度大于64(源码中MIN_TREEIFY_CAPACITY参数),且链表长度大于等于8时(源码中是TREEIFY_THRESHOLD参数),链表会转化为红黑树。另外随着ConcurrentHashMap的自动扩容,一旦链表长度小于6 时(源码中是:UNTREEIFY_THRESHOLD参数),红黑树又会退化为单向链表。

        为什么需要在链表长度大于等于8的时候才转为红黑树呢?hashcode碰撞次数的泊松分布有关,主要是为了达到时间和空间的平衡。在负载因子0.75的情况下,单个hash槽内元素个数为8的情况在百万分之一以内,将7作为分水岭,大于等于8时转为红黑树,小于等于6时转为链表。链表中的元素为8的概率已经非常小了,大于8的情况就更小,所以作者是根据统计概念来选择这一数据的。

ConcurrentHashMap的基本功能:

        ConcurrentHashMap本质是一个HashMap,因此功能与HashMap一样,但是ConcurrentHashMap在HashMap的基本上,提供了并发安全的功能。并发安全功能的实现主要是对指定node节点上加锁来保证数据的安全性的。

ConcurrentHashMap所做的优化

        如何在并发性能与安全性上做好平衡,很多地方都会存在类似的设计,比如CPU的三级缓存,mysql的buffer pool,Synchronized的锁升级等。

        在JDK1.8中,ConcurrentHashMap锁的粒度是node,而JDK1.7及以前是对Segment进行锁定,锁粒度大了,性能也会低很多。

        引入红黑树,在hash冲突较大时,会降低查询的时间复杂度,红黑树查询的时间复杂度为O(logn).

为什么HashMap不允许key为null,但CHM不允许

        HashMap的设计之初就是为了线程在局部使用的,不存在多线程操作的情况,所以存null与否都不影响当前线程自己的操作。

      CoucurrentHashMap的设计就是为了多线程的情况下去使用,如果允许存储null,那在get时,获取了一个null数据,到底是获取到了还是没获取到呢?如果可以为null,多线程情况下必然会引发空指针异常。

Hash冲突的解决

        链地址法:HashMap就是这种方式,基于key的hashcode和桶位置-1做运算,如果出现了相同位置,就形成一个链表挂在后面,在HashMap中因为桶位置 一般不会超过16bit位,所以做了一个高低位的^运算,让高位也参与,这算是多次hash的一个方式。

        多次hash:这个就是针对一个内容,铸多次hash运算,比如先hashcode,然后再用CRC16验证码,让数值不同,布隆过滤器就采用此方式。

        公共溢出区:将hash表分为基准表和溢出表,但凡出现了hash冲突,就将冲突的数据扔到溢出表里。

        开放定址法:有关键字key的哈希值(i),出现冲突时,以这个i地址为基准,产生另一个hash地址i2,若i2还有冲突再次以i为基准找到一个i3,直到找到一个不冲突的地址,将元素扔进去。

  •          线性探测:

                顺序的往后面找哈希地址,比如0有冲突再找1,1冲突再找2,2冲突再......

  •          二次平方探测:

                探查地址时从d入手,首先探查T[d],然后依次探查T[d+d[i]],d[i]为增量序列                1^2,-1^2,2^2,-2^2,……q^2,-q^2(q<=1/2(m-1)),直到探查到有空余地址或者直到T[d-1]为止。

  •          随机数

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值