ConcurrentHashMap相关整理

HashMap不是线程安全的,故多线程时不能用HashMap
HashMap在多线程情况下,在put的时候,插入的元素超过了容量(由负载因子决定)的范围就会触发扩容操作,就是rehash,这个会重新将原数组的内容重新hash到新的扩容数组中,在多线程的环境下,存在同时其他的元素也在进行put操作,如果hash值相同,可能出现同时在同一数组下用链表表示,造成闭环,导致在get时会出现死循环,所以HashMap是线程不安全的。

ConcurrentHashMap底层实现(JDK1.7)
和 HashMap ⼀样,仍然是数组加链表。

ConcurrentHashMap为什么效率高?
原理上来说,ConcurrentHashMap 采⽤了分段锁技术,其中 Segment 继承于 ReentrantLock。
不会像 HashTable 那样不管是 put 还是 get 操作都需要做同步处理。
理论上 ConcurrentHashMap ⽀持CurrencyLevel (Segment 数组数量)的线程并发。

ConcurrentHashMap的get方法为什么不需要加锁
get 逻辑⽐较简单,只需要将 Key 通过 Hash 之后定位到具体的 Segment ,再通过⼀次 Hash 定位到具
体的元素上。
由于 HashEntry 中的 value 属性是⽤ volatile 关键词修饰的,保证了内存可⻅性,所以每次获取时都是
最新值。
ConcurrentHashMap 的 get ⽅法是⾮常⾼效的,因为整个过程都不需要加锁。

ConcurrentHashMap底层实现(JDK1.8)
抛弃了原有的 Segment 分段锁,⽽采⽤了 CAS + synchronized 来保证并发安全性。
跟HashMap很像,也把之前的HashEntry改成了Node,但是作⽤不变,把值和next采⽤了volatile去修
饰,保证了可⻅性,并且也引⼊了红⿊树,在链表⼤于⼀定值的时候会转换(默认是8)。

相关
Hashtable也是线程安全的

Hashtable、ConcurrentHashMap 是不允许键或值为 null 的,为什么?
只考虑他们内部的代码的话,是因为Hashtable内部,put元素时,key为null会报异常,当value为null时,代码内部没有计null的Hash部分的逻辑,所以值也不能为null。
我认为归根接地是设计问题,设计师不想设计null

Hashtable 初始容量为:11

Hashtable的迭代器,一些人说不是“故障快速”,但是官方说是
由所有这个类的“集合视图方法”返回的集合的iterator方法返回的迭代器是故障快速的 :如果Hashtable在迭代器创建之后的任何时间被结构地修改,除了通过迭代器自己的remove方法,迭代器会抛出一个ConcurrentModificationException 。 因此,面对并发修改,迭代器将快速而干净地失败,而不是在未来未确定的时间冒着任意的非确定性行为。 Hashtable的键和元素方法返回的枚举不是故障快速的。

什么是“fail-fast”
当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件。
例如:当某一个线程A通过iterator去遍历某集合的过程中,若该集合的内容被其他线程所改变了;那么线程A访问集合时,就会抛出ConcurrentModificationException异常,产生fail-fast事件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值