java之ConcurrentHashMap

前言

之前的文章对集合整体做了一个介绍,并对其中一些主要的实现类,做了详细的介绍和分析,其中就包含HashMap,但是当时我们呢说它是线程不安全的。那么今天我们就介绍一个线程安全的HashMap,那就是ConcurrentHashMap

ConcurrentHashMap的优势

1.线程不安全的hashmap:之前文章介绍过,为什么hashmap是线程不安全的,那是因为,它的put操作可能导致循环链表的出现,从而出现死循环。
2.hashtable:hashtable虽然是线程安全的,但是我们之前说过,他用的是synchronized关键字,在put方法上,这个就导致它的效率是十分的低下的。
3.ConcurrentHashMap:那么ConcurrentHashMap是怎么既能加锁保持多线程的正确同步,又能保证效率不低下呢。这个就是分段锁的功劳了。分段锁其实就是将一堆数据,分为一块一块的,然后给每一块的数据加上锁,这样就减少了对锁的竞争,提升了效率。

ConcurrentHashMap的结构

下面这个图就是ConcurrentHashMap的大致结构
在这里插入图片描述
图中的HashEntry数组就相当于hashmap里面的entry数组。而这个Segment就相当于一个HashMap。ConcurrentHashMap感觉就像多个HashMap组合在一起。

ConcurrentHashMap初始化

ConcurrentHashMap初始化和当时的hashmap基本差不多,只是当时hashmap初始化的是Entry数组,这里初始化的是segment数组,同样,这个数组长度必须也的是2n次方。
但是它需要多初始化两个变量segementShift和segementMask。这两个,一个是散列运算的位数,一个是散列运算的掩码。
然后就是初始化segment,和初始化hashmap基本一致,可能某些参数不太一样。

ConcurrentHashMap的常见方法

1.get操作
先经过一次散列,定位到segement,然后再经过一次散列,定位到hashentry,最后匹配到元素,取出。这个操作是没有加锁的,原因就是它将需要用到的共享变量,都定义为volatile类型的,这个既不会读到过期变量,也能提升效率(这个前提是没有多线程的写入)。
定位hashentry和segement散列方法一样,但是与的值不一样,定位segement用的是元素通过hashcode再散列后得到的值的高位,而定位hashentry直接使用的是再散列后的值。
2.put操作
由于put方法需要对共享变量进行写入操作,所以为了线程安全,再操作共享变量的时候,必须加锁。
在插入之前需要进行两部操作,第一步就是判断是否需要扩容,第二不就是记录添加元素的位置,将其放在hashentry数组里面。(这个扩容操作和hashmap类似,这里不再赘述)

总结

ConcurrentHashMap采用了一种分段锁的方式,降低了锁冲突。从而实现了,不会牺牲特别多的效率去换取线程的安全。所以,在一些多线程的场景中,大家可以尝试使用ConcurrentHashMap。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mark---小鑫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值