目录
6、remove / replace / replaceAll / clear
ConcurrentSkipListSet是基于ConcurrentSkipListMap实现的线程安全的NavigableSet接口实现类,与之对应的线程不安全的实现类就是基于TreeMap实现的TreeSet;ConcurrentNavigableMap是基于SkipList跳跃表实现的线程安全的NavigableMap实现类,后者对应的线程不安全的实现类就是基于红黑树实现的TreeMap。本篇博客就详细探讨这两类的实现细节。
一、ConcurrentSkipListSet
ConcurrentSkipListSet的类继承关系如下:
其实现的核心接口NavigableSet的另一个典型实现类就是TreeSet,跟TreeSet基于TreeMap实现一样, ConcurrentSkipListSet的实现基于ConcurrentSkipListMap的,添加和删除元素,元素遍历等都是基于ConcurrentSkipListMap方法的,value固定为Boolean.TRUE,其常用方法实现如下:
public ConcurrentSkipListSet() {
m = new ConcurrentSkipListMap<E,Object>();
}
public ConcurrentSkipListSet(Comparator<? super E> comparator) {
m = new ConcurrentSkipListMap<E,Object>(comparator);
}
public boolean add(E e) {
return m.putIfAbsent(e, Boolean.TRUE) == null;
}
public boolean remove(Object o) {
return m.remove(o, Boolean.TRUE);
}
public Iterator<E> iterator() {
return m.navigableKeySet().iterator();
}
public Iterator<E> descendingIterator() {
return m.descendingKeySet().iterator();
}
二、ConcurrentSkipListMap
1、定义
ConcurrentSkipListMap的类继承关系如下:
从上图可知,ConcurrentNavigableMap继承自ConcurrentMap和NavigableMap,后者的典型实现类就是TreeMap,纯粹是基于红黑树实现的,可以参考《java8 TreeMap接口实现源码解析》。ConcurrentNavigableMap没有添加新的方法,只是改写了父类接口的方法定义,如下:
这些方法的用途可以参考API,会挑选其中典型的方法研究其实现细节。该类包含的属性如下:
//头索引节点
private transient volatile HeadIndex<K,V> head;
//比较大小的比较器
final Comparator<? super K> comparator;
//key视图,下面这些视图都是在请求相关方法时才会创建
private transient KeySet<K> keySet;
//键值对视图
private transient EntrySet<K,V> entrySet;
//value视图
private transient Values<V> values;
//倒序遍历的视图
private transient ConcurrentNavigableMap<K,V> descendingMap;
包含的静态常量如下:
//初始化head属性时使用,表示一个空节点
private static final Object BASE_HEADER = new Object();
private static final int EQ = 1;
private static final int LT = 2;
private static final int GT = 0; // Actually checked as !LT
包含的静态属性通过static代码块初始化,如下:
2、Node / Index / HeadIndex
这三个都是内部类,其中Node表示一个键值对,其定义如下:
static final class Node<K,V> {
//键值对的key和value
final K key;
volatile Object value;
//链表中的下一个节点
volatile Node<K,V> next;
Node(K key, Object value, Node<K,V> next) {
this.key = key;
this.value = value;
this.next = next;
}
Node(Node<K,V> next) {
this.key = null;
this.value = this;
this.next = next;
}
//cas修改value
boolean casValue(Object cmp, Object val) {
return UNSAFE.compareAndSwapObject(this, valueOffset, cmp, val);
}
//cas修改next
boolean casNext(Node<K,V> cmp, Node<K,V> val) {
return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
}
boolean isMarker() {
return value == this;
}
boolean isBaseHeader() {
return value == BASE_HEADER;
}
//插入一个value指向自己的节点,next为f的节点
//删除某个节点时会将其value置为null,然后调用此方法在该节点后插入一个marker,将该节点从next链表中移除
//marker在这里是打一个标识同时保存下一个节点的引用,保证将其从next链表中移除失败,即cas修改前一个节点的next属性失败的情形下该节点可以被正常移除
boolean appendMarker(Node<K,V> f) {
return casNext(f, new Node<K,V>(f));
}
//在查询或者修改节点时,发现某个节点的value已经是null了,会调用此方法
//b是前一个节点,f是next节点
void helpDelete(Node<K,V> b, Node<K,V> f) {
if (f == next && this == b.next) {
//再次检查链表关系
if (f == null || f.value != f)
//该节点未插入marker节点,此处重新插入,下次调用时进入else分支
casNext(f, new Node<K,V>(f));
else
//f是一个marker节点
//将this和f都从链表中移除
b.casNext(this, f.next);
}
}
V getValidValue() {
Object v = value;
if (v == t