目录
ConcurrentSkipListMap 的实现原理基于**跳表(SkipList)**数据结构以及并发控制策略。
下面是原理的详解:
一、跳表(SkipList)数据结构:
- 跳表是一种可以代替平衡树的数据结构,其默认是按照Key值升序排列。
- 在跳表中,已排序的数据分布在多层链表中,通过“空间来换取时间”的算法,在每个节点中增加了向前的指针,这样在插入、删除、查找时可以忽略一些不可能涉及到的结点,从而提高了效率。
- 跳表是一种可以用于非平衡查找问题的数据结构。它允许快速在一个有序的序列中查找一个元素。
- 跳表是通过维护多个指向其他节点的链接(对应于排序序列中的“跳过”一些元素)来实现快速查找的。
- 在跳表中,查找、插入和删除操作的时间复杂性为O(log n)。
这样一层套一层的形式,就形成了所谓的跳表。跳表的特性有这么几点:
- 一个跳表结构由很多层数据结构组成。
- 每一层都是一个有序的链表,默认是升序。也可以自定义排序方法。
- 最底层链表(图中所示Level1)包含了所有的元素。
- 如果每一个元素出现在LevelN的链表中(N>1),那么这个元素必定在下层链表出现。
- 每一个节点都包含了两个指针,一个指向同一级链表中的下一个元素,一个指向下一层级别链表中的相同值元素。
跳表的查找示意图:
举例查找11这个数字
跳表的插入示意图:
跳表插入数据的流程如下:
- 找到元素适合的插入层级
K
,这里的K
采用随机的方式。若K
大于跳表的总层级,那么开辟新的一层,否则在对应的层级插入。 - 申请新的节点。
- 调整对应的指针。
假设我要插入元素13(图画的都是自然升序,比较特殊…)原有的层级是3级,假设K
=4:
倘若K
=2:
二、并发控制策略:
ConcurrentSkipListMap
是线程安全的,它支持并发的插入、删除、更新和读取操作。- 为了实现并发控制,
ConcurrentSkipListMap
采用了类似于ConcurrentHashMap
的策略,使用锁分段的技术。不同的段(Segment)可以在不同的线程中进行操作,从而实现真正的并发。 - ConcurrentSkipListMap使用先进的并发控制机制来保证多线程环境下的线程安全性。
- 它采用细粒度的锁,在跳表的每个层级上使用独立的锁,这样可以允许多个修改操作并行进行。
- 通过这种并发控制机制,ConcurrentSkipListMap实现了高并发访问下的高性能。
三、并发插入、删除和更新:
- 当进行插入、删除或更新操作时,
ConcurrentSkipListMap
首先会根据key值定位到相应的段(Segment),然后在该段上加锁进行操作。 - 通过这种方式,不同的线程可以操作不同的段,不会相互干扰,从而实现了高并发。
四、迭代器和Spliterator的弱一致性:
ConcurrentSkipListMap
的迭代器和Spliterator是弱兼容的。这意味着在迭代过程中,如果映射被并发修改(比如其他线程进行了插入或删除操作),那么迭代器可能或可能不反映这些修改。
五、size方法的非精确性:
- 与
ConcurrentHashMap
类似,ConcurrentSkipListMap
的size方法也不是一个常量时间运算。因为映射的异步特性,要得到元素个数必须通过遍历,若在遍历过程中映射被修改(如插入或删除元素),则得到的结果是不精确的。
总结
ConcurrentSkipListMap
结合了跳表的高效查找、插入和删除性能,并通过分段锁的策略实现了高并发。这使得ConcurrentSkipListMap
在多线程环境下成为一种高效且线程安全的数据结构;
它允许快速查找、插入和删除元素,并且支持多个线程同时访问和修改这个映射。