再次聊聊并发编程:并发容器

开发 前端
ConcurrentHashMap 是一种 key 无序的 HashMap,ConcurrentSkipListMap则是 key 有序的, 实现了NavigableMap接口,此接口又继承了SortedMap接口。

一、ConcurrentLinkedQueue/Deque

AQS内部的阻塞队列实现原理:基于双向链表,通过对head/tail进行CAS操作,实现入队和出队。

ConcurrentLinkedQueue 的实现原理和AQS 内部的阻塞队列类似:同样是基于 CAS,同样是通过 head/tail指针记录队列头部和尾部,但还是有稍许差别。

其次,在AQS的阻塞队列中,每次入队后,tail一定后移一个位置;每次出队,head一定后移一个 位置,以保证head指向队列头部,tail指向链表尾部。

但在ConcurrentLinkedQueue中,head/tail的更新可能落后于节点的入队和出队,因为它不是直 接对 head/tail指针进行 CAS操作的,而是对 Node中的 item进行操作。

二、ConcurrentHashMap

HashMap通常的实现方式是“数组+链表”,这种方式被称为“拉链法”。ConcurrentHashMap在这个 基本原理之上进行了各种优化。

首先是所有数据都放在一个大的HashMap中;其次是引入了红黑树。

如果头节点是Node类型,则尾随它的就是一个普通的链表;如果头节点是TreeNode类型,它的后 面就是一棵红黑树,TreeNode是Node的子类。

链表和红黑树之间可以相互转换:初始的时候是链表,当链表中的元素超过某个阈值时,把链表转 换成红黑树;反之,当红黑树中的元素个数小于某个阈值时,再转换为链表。

那为什么要做这种设计呢?

1. 使用红黑树,当一个槽里有很多元素时,其查询和更新速度会比链表快很多,Hash冲突的问 题由此得到较好的解决。

2. 加锁的粒度,并非整个ConcurrentHashMap,而是对每个头节点分别加锁,即并发度,就是 Node数组的长度,初始长度为16。

3. 并发扩容,这是难度最大的。当一个线程要扩容Node数组的时候,其他线程还要读写,因此 处理过程很复杂,后面会详细分析。

由上述对比可以总结出来:这种设计一方面降低了Hash冲突,另一方面也提升了并发度。

三、ConcurrentSkipListMap/Set

ConcurrentHashMap 是一种 key 无序的 HashMap,ConcurrentSkipListMap则是 key 有序的, 实现了NavigableMap接口,此接口又继承了SortedMap接口。

1、ConcurrentSkipListMap

为什么要使用SkipList实现Map?

在Java的util包中,有一个非线程安全的HashMap,也就是TreeMap,是key有序的,基于红黑树实 现。 而在Concurrent包中,提供的key有序的HashMap,也就是ConcurrentSkipListMap,是基于 SkipList(跳查表)来实现的。

这里为什么不用红黑树,而用跳查表来实现呢?

也就是目前计算机领域还未找到一种高效的、作用在树上的、无锁的、增加和删除节点的办法。

2、ConcurrentSkipListSet

ConcurrentSkipListSet只是对ConcurrentSkipListMap的简单封装。

责任编辑:武晓燕 来源: 今日头条
相关推荐

2023-06-14 08:15:34

算法合并操作Winner

2019-11-07 09:20:29

Java线程操作系统

2022-05-02 21:47:13

并发编程线程

2022-03-09 09:43:20

并发编程Java

2023-07-11 08:34:25

参数流程类型

2023-06-30 08:27:20

2024-10-14 12:34:08

2023-07-04 13:36:00

同步工具类Phaser

2022-03-02 08:20:54

并发编程java后端开发

2017-09-19 14:53:37

Java并发编程并发代码设计

2023-11-20 08:01:38

并发处理数Tomcat

2016-11-25 00:38:45

隔离负载均衡系统

2011-12-12 11:16:02

iOS并发编程

2022-10-17 08:07:13

Go 语言并发编程

2011-04-21 16:43:54

BlockingQue

2016-11-25 00:45:37

队列数据

2016-11-28 08:40:17

系统降级服务

2024-08-26 13:23:26

2021-09-06 11:58:24

Python脚本Jmeter

2016-11-28 09:00:10

浏览器浏览器缓存服务端
点赞
收藏

51CTO技术栈公众号