ConcurrentHashMap线程安全的具体实现方式/底层具体实现
发表于|更新于|整理归纳
|总字数:470|阅读时长:1分钟|浏览量:
ConcurrentHashMap 线程安全的具体实现方式/底层具体实现
JDK 1.8 之前
ConcurrentHashMap
是由 Segment
数组结构和 HashEntry
数组结构组成。
Segment
继承了 ReentrantLock
,所以 Segment
是⼀种可重⼊锁,扮演锁的⻆⾊。 HashEntry
⽤于
存储键值对数据。
static class Segment<K,V> extends ReentrantLock implements Serializable {} |
⼀个 ConcurrentHashMap
⾥包含⼀个 Segment
数组, Segment
的个数⼀旦初始化就不能改变。Segment
数组的⼤⼩默认是 16,也就是说默认可以同时⽀持 16 个线程并发写。Segment
的结构和 HashMap 类似,是⼀种数组和链表结构,⼀个 Segment
包含⼀个 HashEntry数组,每个 HashEntry 是⼀个链表结构的元素,每个 Segment
守护着⼀个 HashEntry 数组⾥的元素,当对 HashEntry 数组的数据进⾏修改时,必须⾸先获得对应的 Segment
的锁。也就是说,对同⼀ Segment
的并发写⼊会被阻塞,不同 Segment
的写⼊是可以并发执⾏的。
JDK 1.7 和 JDK 1.8 的 ConcurrentHashMap 实现有什么不同?
- 线程安全实现⽅式:
- JDK 1.7 采⽤ Segment 分段锁来保证安全, Segment 是继承⾃ReentrantLock 。
- JDK1.8 放弃了 Segment 分段锁的设计,采⽤ Node + CAS + synchronized 保证线程安全,锁粒度更细, synchronized 只锁定当前链表或红⿊⼆叉树的⾸节点。
- Hash 碰撞解决⽅法:
- JDK 1.7 采⽤拉链法,JDK1.8 采⽤拉链法结合红⿊树(链表⻓度超过⼀定阈值时,将链表转换为红⿊树)
- 并发度:
- JDK 1.7 最⼤并发度是 Segment 的个数,默认是 16。JDK 1.8 最⼤并发度是 Node 数组的⼤⼩,并发度更⼤。
JDK 1.8 之后
ConcurrentHashMap
取消了 Segment
分段锁,采⽤ Node + CAS + synchronized
来保证并发安全。数据结构跟 HashMap 1.8 的结构类似,数组+链表/红⿊⼆叉树
。Java 8 在链表⻓度超过⼀定阈值(8)时将链表(寻址时间复杂度为 O(N))转换为红⿊树(寻址时间复杂度为 O(log(N)))。
文章作者: MUMU
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 blog.wo0ow.com!