ConcurrentHashMap

ConcurrentHashMap
由于 HashMap 是⼀个线程不安全的容器,主要体现在容量⼤于 总量*负载因⼦ 发⽣扩容时会出现环
形链表从⽽导致死循环。
因此需要⽀持线程安全的并发容器 ConcurrentHashMap 。 在 JDK 1.7 中,ConcurrentHashMap 仍然是数组加链表,和 HashMap 不⼀样的是,
ConcurrentHashMap 最外层并不是⼀个⼤的数组,⽽是⼀个 Segment 的数组,每⼀个 Segment 包
含⼀个和 HashMap 数据结构差不多的链表数组。
ConcurrentHashMap 采⽤了分段锁的技术,Segment 继承于 ReentrantLock,所以我们可以很⽅便
的对每⼀个 Segment 上锁。不会像 HashTable 那样不管是 put 还是 get 操作都需要做同步处理,⼀
个线程占⽤锁访问⼀个 Segment 时,根本不会影响到其他的 Segment。 在 ConcurrentHashMap 的 get ⽅法中,⾮常⾼效,因为全程不需要加锁。只需要将 key 通过 hash
之后定位到具体的 Segment,再通过⼀次 hash 定位到具体的元素上。由于 HashEntry 中的 value
属性是⽤ volatile 关键字修饰的,保证了内存可⻅性,所以每次获取到的值都是最新值。
class Node{
public T value;
public Node parent;
public boolean isRed;
public Node left;
public Node right; }
虽然对 HashEntry 的 value 采⽤了volatile 关键字修饰,但并不能保证并发的原⼦性,所以 put 操作
时仍然需要加锁处理。⾸先是通过 key 的 hash 定位到具体的 Segment,在 put 之前会进⾏⼀次扩容
校验。这⾥⽐ HashMap 要好的⼀点是:HashMap 是插⼊元素之后在看是否需要扩容,有可能扩容
之后后续就没有插⼊就浪费了本次扩容,⽽ HashMap 的扩容是⾮常消耗性能的。⽽
ConcurrentHashMap 不⼀样,它是先将数据插⼊之后再检查是否需要扩容,之后再做插⼊。
⽽在 JDK 1.8 中,抛弃了原有的 Segment 分段锁,⽽采⽤了 CAS + synchronized 来保证并发安全
性。并把 1.7 中存放数据的 HashEntry 改为了 Node,但作⽤还是相同的。其中 value 和 next 均⽤
volatile 保证可⻅性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值