ConcurrentHashMap源码分析JDK8
本文最后更新于:2021年8月29日 晚上
ConcurrentHashMap源码分析JDK8
一、jdk1.8容器初始化
1、源码分析
在
jdk8
的ConcurrentHashMap
中一共有5个构造方法,这四个构造方法中都没有对内部的数组做初始化, 只是对一些变量的初始值做了处理jdk8的ConcurrentHashMap的数组初始化是在第一次添加元素时完成
1 |
|
1 |
|
📌注意,调用这个方法,得到的初始容量和
HashMap
以及jdk7
的ConcurrentHashMap
不同,即使你传递的是一个2的幂次方数,该方法计算出来的初始容量依然是比这个值大的2的幂次方数
1 |
|
1 |
|
1 |
|
2、sizeCtl
含义解释
注意:以上这些构造方法中,都涉及到一个变量
sizeCtl
,这个变量是一个非常重要的变量,而且具有非常丰富的含义,它的值不同,对应的含义也不一样,这里我们先对这个变量不同的值的含义做一下说明,后续源码分析过程中,进一步解释
sizeCtl
为0,代表数组未初始化, 且数组的初始容量为16
sizeCtl
为正数,如果数组未初始化,那么其记录的是数组的初始容量,如果数组已经初始化,那么其记录的是数组的扩容阈值0.75n
sizeCtl
为-1,表示数组正在进行初始化
sizeCtl
小于0,并且不是-1,表示数组正在扩容, -(1+n),表示此时有n个线程正在共同完成数组的扩容操作
二、jdk1.8添加安全
1、源码分析
1.1、添加元素put/putVal方法
1 |
|
CHM
不允许有 空值或空键int hash = spread(key.hashCode())
扰动函数生成哈希值,(h ^ (h >>> 16)) & HASH_BITS
:高十六位参与哈希值运算,同时& 0x7fffffff
即0111 1111 1111 1111 1111 1111 1111 1111
高位为0,得到的哈希值必然为 正数- 在
else
里只对待插入桶f
加锁,不影响table
的其他元素,保证了安全和高效 - 进入
else
后又进行桶头结点的判断,防止其他线程在插入之前,将桶结构树化,因为 树化treeifyBin
在synchronized
之外
1 |
|
通过以上源码,我们可以看到,当需要添加元素时,会针对当前元素所对应的桶位进行加锁操作,这样一方面保证元素添加时,多线程的安全,同时对某个桶位加锁不会影响其他桶位的操作,进一步提升多线程的并发效率
1.2、数组初始化,initTable方法
1 |
|
2、图解
2.1、put加锁图解
三、jdk1.8扩容安全
- 线程
1、源码分析
1 |
|
2、图解
四、jdk1.8多线程扩容效率改进
多线程协助扩容的操作会在两个地方被触发:
① 当添加元素时,发现添加的元素对用的桶位为fwd节点,就会先去协助扩容,然后再添加元素
② 当添加完元素后,判断当前元素个数达到了扩容阈值,此时发现sizeCtl的值小于0,并且新数组不为空,这个时候,会去协助扩容
1、源码分析
1.1、元素未添加,先协助扩容,扩容完后再添加元素
1 |
|
1 |
|
1.2、先添加元素,再协助扩容
1 |
|
注意:扩容的代码都在transfer方法中,这里不再赘述
2、图解
五、集合长度的累计方式
1、源码分析
1.1、addCount方法
① CounterCell数组不为空,优先利用数组中的CounterCell记录数量
② 如果数组为空,尝试对baseCount进行累加,失败后,会执行fullAddCount逻辑
③ 如果是添加元素操作,会继续判断是否需要扩容
1 |
|
1.2、fullAddCount方法
① 当CounterCell数组不为空,优先对CounterCell数组中的CounterCell的value累加
② 当CounterCell数组为空,会去创建CounterCell数组,默认长度为2,并对数组中的CounterCell的value累加
③ 当数组为空,并且此时有别的线程正在创建数组,那么尝试对baseCount做累加,成功即返回,否则自旋
1 |
|
2、图解
fullAddCount方法中,当as数组不为空的逻辑图解
六、jdk1.8集合长度获取
size
的获取,如果线程可以将大小直接加入到baseCount
则结束- 否则就尝试加到
counterCells
里,此数组会有扩容机制。加不进去,则随机加入到counterCells
的其他位置,这点在fullAddCount
有体现出来
1、源码分析
1.1、size方法
1 |
|
1.2、sumCount方法
1 |
|
注意:这个方法并不是线程安全的
🔗Reference
https://www.bilibili.com/video/BV17i4y1x71z
https://blog.csdn.net/woaiwym/article/details/80675789
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!