并发编程学习之Java学习

Java容器 --- ConcurrentHashMap分析

2021-07-12  本文已影响0人  _code_x

ConcurrentHashMap 引出

HashMap在多线程环境下存在线程安全问题,一般的解决方案:

ps:Hashtable与ConcurrentHashMap的区别

hashtable全表锁 jdk1.7分段锁 jdk1.8锁定Node节点(CAS + synchronized实现)

ConcurrentHashMap 的实现原理是什么?

底层数据结构和HashMap jdk1.7和jdk1.8基本一致(查询时间复杂度不同)。

多线程并发问题:

ConcurrentHashMap 在 JDK1.7 和 JDK1.8 解决并发安全问题(安全机制:粒度不同)

拓展:CAS是什么?自旋又是什么?

JDK1.8 中为什么使用内置锁 synchronized替换 可重入锁 ReentrantLock?

拓展:什么是可重入锁?有哪些?

拓展:synchronized的可重入怎么实现?

拓展:ReentrantLock还可以实现公平锁机制。什么叫公平锁呢?也就是在锁上等待时间最长的线程将获得锁的使用权。通俗的理解就是谁排队时间最长谁先执行获取锁。

ConcurrentHashMap 的 put 方法执行逻辑是什么?

jdk1.7:

jdk1.8:

ConcurrentHashMap 的 get 方法执行逻辑是什么?

jdk1.7:

由于 HashEntry 涉及到的共享变量都使用 volatile 修饰,volatile 可以保证内存可见性,所以每次获取时都是最新值。

jdk1.8:

ConcurrentHashMap 的 get 方法是否要加锁,为什么?

get 方法不需要加锁。因为 Node 的元素 value 和指针 next 是用 volatile 修饰的,在多线程环境下线程A修改节点的 value 或者新增节点的时候是对线程B可见的。

这也是它比其他并发集合比如 Hashtable、用 Collections.synchronizedMap()包装的 HashMap 效率高的原因之一。

拓展:get 方法不需要加锁与 volatile 修饰的哈希桶数组有关吗?

没有关系。哈希桶数组table用 volatile 修饰主要是保证在数组扩容的时候保证可见性。

拓展:volatile

为什么Hashtable, ConcurrentHashMap 的 key和value 不能为null(并发角度分析)

ConcurrentHashmap和Hashtable都是支持并发的,二者规定key,value均不能为null,null的话,会抛出空指针异常。

HashMap允许key和value为null,在单线程时,调用contains()和get()不会出现问题,但是多线程下,就是线程不安全的。如果要保证线程安全,应该使用ConcurrentHashMap 。

快速失败(fail—fast)

快速失败(fail—fast)是java集合中的一种机制, 在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进行了修改(增加、删除、修改),则会抛出Concurrent Modification Exception。

Tip:这里异常的抛出条件是检测到 modCount!= expectedmodCount 这个条件。如果集合发生变化时修改modCount值刚好又设置为了expectedmodCount值,则异常不会抛出。因此,不能依赖于这个异常是否抛出而进行并发操作的编程,这个异常只建议用于检测并发修改的bug。

java.util包下的集合类都是快速失败的,不能在多线程下发生并发修改(迭代过程中被修改)算是一种安全机制吧。

拓展:安全失败(fail—safe)大家也可以了解下,java.util.concurrent包下的容器都是安全失败,可以在多线程下并发使用,并发修改。

ConcurrentHashMap 的并发度是什么?

ConcurrentHashMap 迭代器是强一致性还是弱一致性?

巨人的肩膀:

https://aobing.blog.csdn.net/article/details/103589011
https://blog.csdn.net/yunzhaji3762/article/details/113623168

上一篇下一篇

猜你喜欢

热点阅读