ConcurrentSkipListMap源码---JDK1.8
Posted emoji-emoji
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ConcurrentSkipListMap源码---JDK1.8相关的知识,希望对你有一定的参考价值。
private V doPut(K key, V value, boolean onlyIfAbsent) { Node<K,V> z; // added node if (key == null) throw new NullPointerException(); Comparator<? super K> cmp = comparator; outer: for (;;) { //找到key对应的前继节点b for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) { //如果n不为null if (n != null) { Object v; int c; //获取n的next节点 Node<K,V> f = n.next; //发生竞争,break if (n != b.next) // inconsistent read break; //如果n已经被删除 if ((v = n.value) == null) { // n is deleted n.helpDelete(b, f); break; } //如果b已经被删除 if (b.value == null || v == n) // b is deleted break; //如果c>0,说明当前节点应该排在n的后面,所以从n后面继续比较 if ((c = cpr(cmp, key, n.key)) > 0) { b = n; n = f; continue; } //如果键相等 if (c == 0) { if (onlyIfAbsent || n.casValue(v, value)) { @SuppressWarnings("unchecked") V vv = (V)v; return vv; } break; // restart if lost race to replace value } // else c < 0; fall through } //如果n为null,说明b是链表的最后一个节点, //直接根据key,value,n创建一个新节点 z = new Node<K,V>(key, value, n); //原子替换next域 if (!b.casNext(n, z)) break; // restart if lost race to append to b break outer; } } //生成随机数,随机提拔节点 int rnd = ThreadLocalRandom.nextSecondarySeed(); //判断是否需要增加level if ((rnd & 0x80000001) == 0) {// test highest and lowest bits int level = 1, max; while (((rnd >>>= 1) & 1) != 0) ++level; Index<K,V> idx = null; //保存头节点 HeadIndex<K,V> h = head; //如果level小于跳表的层级 if (level <= (max = h.level)) { //为节点生成对应的Index节点 for (int i = 1; i <= level; ++i) //依次赋值Index节点,并赋值节点的down域 idx = new Index<K,V>(z, idx, null); } else { // try to grow by one level level = max + 1; // hold in array and later pick the one to use //生成Index节点的数组 @SuppressWarnings("unchecked")Index<K,V>[] idxs = (Index<K,V>[])new Index<?,?>[level+1]; //依次生成Index节点,并赋值down域 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) // lost race to add level break; HeadIndex<K,V> newh = h; //保存头节点对应的Node节点 Node<K,V> oldbase = h.node; //为每一层生成一个头节点 for (int j = oldLevel+1; j <= level; ++j) newh = new HeadIndex<K,V>(oldbase, newh, idxs[j], j); //原子交换头节点 if (casHead(h, newh)) { //h重新赋值为最高层的头节点 h = newh; //idx赋值为旧层级的头节点,将level设置为之前的层级 idx = idxs[level = oldLevel]; break; } } } // find insertion points and splice in //插入Index节点 splice: for (int insertionLevel = level;;) { //保存新跳表的层级 int j = h.level; for (Index<K,V> q = h, r = q.right, t = idx;;) { //头节点或者idx节点为空 if (q == null || t == null) //跳出循环 break splice; //如果right节点不为空 if (r != null) { //保存r的node Node<K,V> n = r.node; // compare before deletion check avoids needing recheck int c = cpr(cmp, key, n.key); if (n.value == null) { if (!q.unlink(r)) break; r = q.right; continue; } if (c > 0) { q = r; r = r.right; continue; } } if (j == insertionLevel) { //r节点插入q与t之间 if (!q.link(r, t)) break; // restart //t节点的值为null,需要删除 if (t.node.value == null) { findNode(key); break splice; } if (--insertionLevel == 0) break splice; } if (--j >= insertionLevel && j < level) t = t.down; q = q.down; r = q.right; } } } return null; }
以上是关于ConcurrentSkipListMap源码---JDK1.8的主要内容,如果未能解决你的问题,请参考以下文章
ConcurrentSkipListMap源码---JDK1.8