ConcurrentHashMap简介
ConcurrentHashMap
是线程安全的 HashMap, JDK1.7 的 ConcurrentHashMap
底层采用 分段的数组+链表 实现,JDK1.8 采用的数据结构跟 HashMap1.8
的结构一样,数组+链表/红黑二叉树。
存储结构
JDK1.7 ConcurrentHashMap底层数据结构
ConcurrentHashMap将数据分成一个一个Segment,
Segment
是一种可重入锁,当一个线程占用锁访问其中一个段数据时,其他段的数据也能被其他线程访问。
ConcurrentHashMap put数据的流程
1. 计算key的位置,获取其所在的segment
2. 如果所在segment为空,则需要对其segment进行初始化
3. 判断Segment是否为null , 如果为null ,则使用 Segment[0]
的容量和负载因子创建一个 HashEntry
数组
4. 判断Segment是否为null , 使用创建的 HashEntry
数组初始化这个 Segment.
5. 自旋判断计算得到的指定位置的 Segment
是否为 null,使用 CAS 在这个位置赋值为 Segment
.
6. 调用Segment.put
插入 key,value 值
JDK1.8 ConcurrentHashMap 存储结构
put方法
1. 根据 key 计算出 hashcode 。
2. 判断是否需要进行初始化。
3. 即为当前 key 定位出的 Node,如果为空表示当前位置可以写入数据,利用 CAS 尝试写入,失败则自旋保证成功。
4. 如果当前位置的 hashcode == MOVED == -1
,则需要进行扩容。
5. 如果都不满足,则利用 synchronized 锁写入数据。
6. 如果数量大于 TREEIFY_THRESHOLD
则要执行树化方法,在 treeifyBin
中会首先判断当前数组长度 ≥64 时才会将链表转换为红黑树。