线程安全的集合——ConcurrentHashMap

为什么HashMap集合是线程不安全的?

① 同时put碰撞导致数据丢失:多个线程同时执行put操作,计算出来的hashcode值相等,插入到同一位置导致有的数据被覆盖

② 同时put扩容导致数据丢失:多个线程执行put操作时同时发现需要扩容,也会发生数据丢失

③ 死循环导致CPU100%

ConcurrentHashMap JDK1.7的底层实现
Java 7中的ConcurrentHashMap最外层是多个segment,每个segment的底层数据结构与JDK 1.7的HashMap类似,是基于数组加链表实现的;每个segment独立上ReentrantLock(分段可重入锁),每个segment之间互不影响,提高了并发效率;ConcurrentHashMap默认有16个segment,所以最多可以同时支持16个并发线程写(操作分别分布在不同的segment上),这个默认值可以在初始化的时候设置为其它值,但是一旦初始化之后,是不可以扩容的
在这里插入图片描述
ConcurrentHashMap JDK1.8的底层实现
Java 8中的ConcurrentHashMap是由一个个的节点组成,每个节点的底层数据结构与JDK 1.8的HashMap类似,是基于数组加链表加红黑树实现的
在这里插入图片描述
JDK1.8 putVal 方法的流程: 判断key value不为空(这要与HashMap区分开,HashMap支持key 和 value都为空,ConcurrentHashMap不支持)-> 计算hash值->根据对应位置节点的类型来赋值,或者helpTransfer,或者增长链表,或者给红黑树增加节点->检查满足阀值就转化成红黑树->返回oldVal

JDK1.8 get 方法的流程: 计算hash值->找到对应的位置,分不同情况进行->要么直接取值、要么红黑树找值、要么是链表找值->返回结果

JDK1.7保证线程安全的机制: 使用的是分段锁,也就是为每一个segment加上ReentrantLock锁

JDK1.8保证线程安全的机制: 使用的是CAS机制加上synchronized锁

JDK1.8的HashMap和ConcurrentHashMap为什么设置链表节点超过8就转成红黑树?

因为如果链表节点超过8,那么会导致查询效率非常低,转成红黑树后,复杂度由原来的O(n)转成了O(logn);链表节点超过8的概率是非常小的,一般会出现这种情况最有可能的是哈希算法有问题,为了出现这种情况,才有了转化成红黑树的机制

之所以不一开始就直接使用红黑树来存储,是因为红黑树每个节点占用的地址空间是链表的两倍,为了节省内存空间,一开始采用的是链表存储

注意:ConcurrentHashMap的key和value都不能为空

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值