# ConcurrentSkipListMap
# 原理
跳表:一种加了索引的链表
复杂度:log(n)
以多层链表的形式实现,每一层都下一层的部分节点,可以看成上层是下层的索引。
最底层是全部的数据,按顺序存储的链表。
主要三种节点
- 头节点:无数据,有层级属性
- 普通节点:数据节点,next指针
- 索引节点:数据,next指针,down指针
删除操作
- cas将节点值更新为null。表示节点已删除,next指针还需要变更。
- cas将next的节点更新为marker节点。
- cas将前面节点的next指针指向其后面节点,从而跳过当前节点
# 实现
# 节点实现
static final class Node<K,V> {
final K key;
volatile Object value;
volatile Node<K,V> next;
boolean isMarker() {
return value == this;
}
boolean isBaseHeader() {
return value == BASE_HEADER;
}
void helpDelete(Node<K,V> b, Node<K,V> f) {
if (f == next && this == b.next) {
if (f == null || f.value != f) // not already marked
casNext(f, new Node<K,V>(f));
else
b.casNext(this, f.next);
}
}
- 当value==this表示当前节点是个marker节点
- 当value等于一个特殊空对象时表示一个头节点
- 删除节点,输入前,后两个节点,删除当前节点
删除需要多个阶段,一次调用只处理一个阶段的方法
# 索引节点
static class Index<K,V> {
final Node<K,V> node;
final Index<K,V> down;
volatile Index<K,V> right;
final boolean indexesDeletedNode() {
return node.value == null;
}
final boolean link(Index<K,V> succ, Index<K,V> newSucc) {
Node<K,V> n = node;
newSucc.right = succ;
return n.value != null && casRight(succ, newSucc);
}
final boolean unlink(Index<K,V> succ) {
return node.value != null && casRight(succ, succ.right);
}
- node.value是null时表示该节点已经删除
- link方法表示插入一个后继节点
- unlink删除一个索引节点
# 头节点
static final class HeadIndex<K,V> extends Index<K,V> {
final int level;
HeadIndex(Node<K,V> node, Index<K,V> down, Index<K,V> right, int level) {
super(node, down, right);
this.level = level;
}
}
一个特殊的索引节点