java.util.concurrent.ConcurrentHashMap实现原理

HashMap并发先会出现什么问题那?

JDK中有了HashTable为何还要有个ConcurrentHashMap?

首先我们都知道HashMap不是线程安全的,但在什么情况下出会出现并发问题那?

HashMap:
    HashMap的数据结构:数组、链表、红黑树(jdk1.8),


    HashMap的原理:
        1.自动扩容
            数组默认大小:16
            当数组的存储比例达到负载因子临界点时(默认75%),数组将会自动扩容为原来的2倍
        2.hash算法
            所有的对象都有hashCode(使用key的)
            HashMap中的key的计算公式=(key.hashCode)^(key>>> 16)
        3.数组下标
            数据下标 = hashCode%(16-1) = hashCode%16
        4.Hash冲突
            不同对象算出来的数据下标相同的时,就发送了hash冲突
            当发生hash冲突时数据将会以链表的方式存储,当链表长度大于8的时候,将后面的数据存在红黑树中

                                         

由于HashMap 不是线程安全有可能在并发情况下发送以下问题:
1.数据丢失
    如果多个线程同时put相同的key时,那么其中一个线程的数据将会丢失或get不到了
2.Map.size()与实际不合
    多线程环境下put的HashMap会被“损坏”,其中会造成size与实际不符合
3.导致死循环
    当HashMap在做动态扩容是,需要对整个Hash表里的无素都需要被重算一遍。这叫rehash,
    并发环境下的rehash过程可能会带来循环链表,导致死循环致使线程挂掉。
    参考:疫苗:JAVA HASHMAP的死循环

为了解决这些问题JDK提供了2个线程安全的HashMap,HashTable和ConcurrentHashMap
HashTable 底层使用了synchronized,对所有的方法增加了锁,就解决了并发问题,但同时降低了效率
为了解决效率问题,JDK又提供了一个既能保持线程安全,有可以解决效率问题的工具类ConcurrentHashMap

ConcurrentHashMap原理:

分段锁

 HashTable容器在竞争激烈的并发环境下表现出效率低下的原因,是因为所有访问HashTable的线程都必须竞争同一把锁,那假如容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效的提高并发访问效率,这就是ConcurrentHashMap所使用的锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。

简单的说就是把数组问题多个段,每个段各有一把锁。JDK1.8后则改为每个数组的元素一个锁

参考:Java集合---ConcurrentHashMap原理分析
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值