ConcurrentHashMap

ConcurrentHashMap的设计和原理:

设计:
先说一下HashMap和HashTable

  • 这两种数据结构都是数组+链表;
  • HashMap允许多个线程同时进行存取,但是不能保证因为多线程的原因导致获取的数据不是想要的;
  • HashTable存取都加上了Synchronized,因此只能允许同时一个线程进行存取,但是存取的数据都是想要的。
    为了解决HashMap和HashTable的问题,设计了ConcurrentHashMap,它同时允许多个线程同时进行存取,并且存取的数据都是想要的。

Java1.7版本 分段锁机制:
维护一个Segment数组,Segment里面维护一个HashEntry数组,每个HashEntry数组元素存放一个HashEntry链表的头节点,注意Java1.7这里没有引入红黑树。(Segment继承ReentrantLock)
同一个Segment的存取操作对应一把锁。

Java1.8版本 volatile + CAS + Synchronized:

  • 内部维护一个Node数组,在put操作时才会去初始化Node数组。volatile修饰的sizeCtl成员,>=0表示未初始化,=-1表示正在初始化,=-n表示有n个线程正在等待初始化完成。
    初始化时,正在初始化的线程使用CAS替换sizeCtl为-1(不成功则循环),成功后初始化Node数组。正在等待的线程则是循环执行Thread.yeild()让出CPU资源。
  • 当需要插入一个元素,此时Node数组对应位置没有元素,则使用CAS将这个元素替换,成功则返回,不成功则进入for的下一次循环。
  • 当Node数组对应的位置已经有元素了,那么就进入这个Node对应的链表或红黑树,此时这个Synchronized锁住这个Node。

既然ConcurrentHashMap是线程安全的,那为什么还要使用HashMap呢?

HashMap支持null作为key和value,但是ConcurrentHashMap不支持null作为key和value。
在Map.get(key)返回null时,不知道是没有key映射还是key为null的映射为null,可以通过containsKey()来判断。
HashMap在单一线程下使用,因此能够确保containsKey(null)和get(null)操作的是同一个HashEntry;
而ConcurrentHashMap在多线程下使用,因此不能确保containsKey(null)和get(null)操作的是同一个Node()。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值