[JDK源码]-J.U.C-ConcurrentSkipListMap

由于作者水平有限,如有什么错误点,多谢指出。

ConcurrentSkipListMap

/*头节点          	   索引节点(最底层保存的是 数据节点 其他层保存的是 索引节点)
* +-+    right        +-+                      +-+
* |2|---------------->| |--------------------->| |->null
* +-+                 +-+                      +-+
*  | down              |                        |
*  v                   v                        v
* +-+            +-+  +-+       +-+            +-+       +-+
* |1|----------->| |->| |------>| |----------->| |------>| |->null
* +-+            +-+  +-+       +-+            +-+       +-+
*  v              |    |         |              |         |
* Nodes  next     v    v         v              v         v
* +-+  +-+  +-+  +-+  +-+  +-+  +-+  +-+  +-+  +-+  +-+  +-+
* | |->|A|->|B|->|C|->|D|->|E|->|F|->|G|->|H|->|I|->|J|->|K|->null
*/
public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
    implements ConcurrentNavigableMap<K,V>, Cloneable, Serializable {
    //链表头部的 特殊值
    private static final Object BASE_HEADER = new Object();
 
    // 跳表 最顶层索引
    private transient volatile HeadIndex<K,V> head;

    // 比较器 K按照什么比较
    final Comparator<? super K> comparator;

    /** Lazily initialized key set */ //懒加载的 几个集合
    private transient KeySet<K> keySet;
    /** Lazily initialized entry set */
    private transient EntrySet<K,V> entrySet;
    /** Lazily initialized values collection */
    private transient Values<V> values;
    /** Lazily initialized descending key set */
    private transient ConcurrentNavigableMap<K,V> descendingMap;
    //保存K-V的节点
    static final class Node<K,V> {
        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;
        }
        //创建一个新的标记节点。 标记的区别在于它的值字段指向它自己。  
        //创建新的标记节点,在删除节点时使用,注意这里的节点 k null v 指向它自己
        Node(Node<K,V> next) {
            this.key = null;
            this.value = this;
            this.next = next;
        }
    }
    // 跳表的索引节点, 层级结构
    static class Index<K,V> {
        final Node<K,V> node;
        final Index<K,V> down;
        volatile Index<K,V> right;
    }
    //每层 index 索引节点的头节点
    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;
        }
    }
    //默认构造
    public ConcurrentSkipListMap() {
        this.comparator = null;
        initialize();
    }
}

initialize初始化

private void initialize() {
    keySet = null;
    entrySet = null;
    values = null;
    descendingMap = null;
    //初始化头部索引节点 
    head = new HeadIndex<K,V>(new Node<K,V>(null, BASE_HEADER, null),
                              null, null, 1);
}

put操作

public V put(K key, V value) {
    if (value == null)
        throw new NullPointerException();
    return doPut(key, value, false);
}
private V doPut(K key, V value, boolean onlyIfAbsent) {
    Node<K,V> z;             // 要添加的节点
    if (key == null)
        throw new NullPointerException();
    Comparator<? super K> cmp = comparator; //比较器
    outer: for (;;) {//循环  直到插入node节点
        //找到 k要放的的位置的  前一个和后一个节点 b n
        for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {
            if (n != null) {	//b后边还有节点
                Object v; int c;
                Node<K,V> f = n.next;	//n的下一个节点
                if (n != b.next)               // n不是 b的下一个节点了  重新开始 
                    break;
                if ((v = n.value) == null) {   // n 被删除了, 帮助删除,重试
                    n.helpDelete(b, f);
                    break;
                }
                if (b.value == null || v == n) // b被删除了
                    break;
                if ((c = cpr(cmp, key, n.key)) > 0) {//当前k 和 n的k比较, 需不需要更新
                    b = n;
                    n = f;
                    continue;
                }
                if (c == 0) {	//二者相等
                    //如果onlyIfAbsent 设置为true,不进行旧值替换,否则替换旧值并返回旧值
                    if (onlyIfAbsent || n.casValue(v, value)) {
                        @SuppressWarnings("unchecked") V vv = (V)v;
                        return vv;
                    }
                    break; // 如果 失败,此时退出当前循环 重试 
                }
            }
			//找到了插入当前的位置
            z = new Node<K,V>(key, value, n);
            if (!b.casNext(n, z))
                break;         // CAS将b的next修改为z ,失败重试
            break outer;//退出外循环 完成插入
        }
    }
	// 插入成功  是否需要更新索引
    int rnd = ThreadLocalRandom.nextSecondarySeed(); //当前线程获取一个随机数
    if ((rnd & 0x80000001) == 0) { //10000000000000000000000000000001  & 随机数 :最高最低 是不是1
        int level = 1, max;
        while (((rnd >>>= 1) & 1) != 0)//当前节点应该处于的层级  (随机数右移 & 1) 
            ++level;
        Index<K,V> idx = null;
        HeadIndex<K,V> h = head;	//索引链表的头节点
        if (level <= (max = h.level)) {	//当前节点的层数 <= 头节点的层数
            for (int i = 1; i <= level; ++i)	
                idx = new Index<K,V>(z, idx, null);
        }
        else { // 当前层大于 head 的层 
            level = max + 1; // 当前level 设置为 原 + 1
            //创建层级索引 数组
            @SuppressWarnings("unchecked")Index<K,V>[] idxs =
                (Index<K,V>[])new Index<?,?>[level+1];
            for (int i = 1; i <= level; ++i)//创建层级索引	
                idxs[i] = idx = new Index<K,V>(z, idx, null);
            for (;;) {// 更新头节点
                h = head;	//原头节点
                int oldLevel = h.level;//原 层
                if (level <= oldLevel) // 如果已经 小于了 原层,表示其他线程更新了  退出
                    break;
                HeadIndex<K,V> newh = h;
                Node<K,V> oldbase = h.node;	//原头节点指向的 node
                for (int j = oldLevel+1; j <= level; ++j)//创建每一层 索引的头节点
                    // 头节点的 right 节点指向当前 idxs[j]   层数为j
                    newh = new HeadIndex<K,V>(oldbase, newh, idxs[j], j);
                if (casHead(h, newh)) {//更新索引节点的 头节点
                    h = newh;	//h为最新的头节点
                    idx = idxs[level = oldLevel]; //当前索引节点为 level 下标处的节点
                    break;
                }
            }
        }
        // 找到插入点并拼接进去	
        splice: for (int insertionLevel = level;;) {//从最顶层 level开始
            int j = h.level;	//头节点的层数
            for (Index<K,V> q = h, r = q.right, t = idx;;) {//循环直到插入成功
                if (q == null || t == null)//头节点或者刚 创建的节点已经被删除
                    break splice;
                if (r != null) {//q 是不是最后一个
                    Node<K,V> n = r.node;
                    // 比较当前K 和 right索引的 node节点的 V的值
                    int c = cpr(cmp, key, n.key);
                    if (n.value == null) {//如果 n的V为空
                        if (!q.unlink(r))//q的 next指向 r的next  失败重试  成功 获取新的 right节点
                            break;
                        r = q.right;
                        continue;
                    }
                    if (c > 0) {
                        q = r;	//更新q为右边索引
                        r = r.right;//r 更新为原来r 的 right 节点
                        continue;
                    }
                }
				//头节点的层 等于 待插入的 层
                if (j == insertionLevel) {
                    if (!q.link(r, t))// 节点插入q r 中间
                        break; // 失败重试
                    if (t.node.value == null) {//node 节点被删除 调用findNode - 删除中间被删除的节点,然后停止索引节点插入
                        findNode(key);
                        break splice;
                    }
                    //全部插入完成
                    if (--insertionLevel == 0)
                        break splice;
                }
				//从 索引头节点往下寻找 找到正确的插入的 层
                if (--j >= insertionLevel && j < level)
                    t = t.down;
                q = q.down;	//层 下移
                r = q.right;//获取新的 right节点
            }
        }
    }
    return null;
}

get方法

首先通过 head索引节点获取到层级的 头节点然后 这个节点找到 下一个索引节点 去判断

public V get(Object key) {
    return doGet(key);
}

private V doGet(Object key) {
    if (key == null)
        throw new NullPointerException();
    Comparator<? super K> cmp = comparator;
    outer: for (;;) {
        //findPredecessor 找到小于给定K 的前一个节点  以及下一个节点 n
        for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {
            Object v; int c;
            if (n == null)//b是最后一个节点 退出
                break outer;
            Node<K,V> f = n.next; 	//获取n的下一个节点
            if (n != b.next)                // b的next发生了改变
                break;
            if ((v = n.value) == null) {    // n删除了
                n.helpDelete(b, f);
                break;
            }
            if (b.value == null || v == n)  // b 删除了
                break;
            if ((c = cpr(cmp, key, n.key)) == 0) {//比较n的k和传入的k, 如果相同返回 V值
                @SuppressWarnings("unchecked") V vv = (V)v;
                return vv;
            }
            if (c < 0)//表示K 的值小于 n的值,表示链表中 不存在
                break outer;
            b = n;//往后继续查找
            n = f;
        }
    }
    return null;
}
//找到小于给定K的前一个节点 
private Node<K,V> findPredecessor(Object key, Comparator<? super K> cmp) {
    if (key == null)
        throw new NullPointerException(); // don't postpone errors
    for (;;) {
        //索引节点的头节点 和 right 节点
        for (Index<K,V> q = head, r = q.right, d;;) {
            if (r != null) {//右节点存在
                Node<K,V> n = r.node;
                K k = n.key;	
                if (n.value == null) { //n被删除了
                    if (!q.unlink(r))	//尝试断开r
                        break;           
                    r = q.right;         // 读取新的右节点
                    continue;
                }
                if (cpr(cmp, key, k) > 0) { // 当前K 大于节点 n的值,根据索引节点往后查找
                    q = r;
                    r = r.right;
                    continue;
                }
            }
            //下一层找,如果是最后溢出 q.node 就是找到的节点
            if ((d = q.down) == null)
                return q.node;
            q = d;// 更新q 下降后的
            r = d.right; //右  也更新
        }
    }
}

remove

public V remove(Object key) {
    return doRemove(key, null);
}
final V doRemove(Object key, Object value) {
    if (key == null)
        throw new NullPointerException();
    Comparator<? super K> cmp = comparator;
    outer: for (;;) {
        //先找到 给定K 的  前面的节点b 和 后面 n
        for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {
            Object v; int c;
            if (n == null) //n 不存在
                break outer;
            Node<K,V> f = n.next;	//n的 next  f
            if (n != b.next)                    // n 不是 b的next了
                break;
            if ((v = n.value) == null) {        // n被删 
                n.helpDelete(b, f);
                break;
            }
            if (b.value == null || v == n)      // b 被删
                break;
            if ((c = cpr(cmp, key, n.key)) < 0) //如果 n 的K 大于 给定的K,n不是要找的k
                break outer;
            if (c > 0) {//n的K 小于给定的K, 可能其他线程插入了比K小的,往前找,更新 b n
                b = n;
                n = f;
                continue;
            }
            //如果 value 不为空  和当前n 的value 比较,不等退出
            if (value != null && !value.equals(v))
                break outer;
            if (!n.casValue(v, null)) //n的value 设置为null 
                break;
            if (!n.appendMarker(f) || !b.casNext(n, f))//清除, b的next设置为 f
                findNode(key);                  // 如果其他线程完成了  findNode(返回满足当前K的节点,并删除沿途发现的已经被删除的节点)
            else {
                findPredecessor(key, cmp);     // 删除成功  findPredecessor(删除n的索引节点)
                if (head.right == null)
                    tryReduceLevel();
            }
            @SuppressWarnings("unchecked") V vv = (V)v;
            return vv;
        }
    }
    return null;
}

ConcurrentSkipListSet

就是通过Map 来实现的

public class ConcurrentSkipListSet<E>
    extends AbstractSet<E>
    implements NavigableSet<E>, Cloneable, java.io.Serializable {
    public ConcurrentSkipListSet() {
        m = new ConcurrentSkipListMap<E,Object>();
    }
    public boolean add(E e) {
    	return m.putIfAbsent(e, Boolean.TRUE) == null;
	}
    
    public boolean remove(Object o) {
    	return m.remove(o, Boolean.TRUE);
	}
    
    public boolean contains(Object o) {
        return m.containsKey(o);
    }
    
    
}
  • 13
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值