JDKソース--ConcurrentSkipListMap(ジャンプテーブル)
げんり Redis秩序化集合で使用され,赤黒樹と同じ時間効率を達成したが,より簡単に実現した.
データの読み込み
データの書き込み
データの削除
データの読み込み
private V doGet(Object key) {
if (key == null)
throw new NullPointerException();
Comparator<? super K> cmp = comparator;
// , , 。
outer: for (;;) {
// key //b key , head
for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {
Object v; int c;
// , , null
if (n == null)
break outer;
Node<K,V> f = n.next;
//b , ( )
if (n != b.next) // inconsistent read
break;
// null, , 。
if ((v = n.value) == null) { // n is deleted
n.helpDelete(b, f);
break;
}
// ,
if (b.value == null || v == n) // b is deleted
break;
// key , (n.value)
if ((c = cpr(cmp, key, n.key)) == 0) {
@SuppressWarnings("unchecked") V vv = (V)v;
return vv;
}
// key, key ,
if (c < 0)
break outer;
// ,
b = n;
n = f;
}
}
return null;
}
データの書き込み
// , , null
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 (;;) {
for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {
if (n != null) {
Object v; int c;
Node<K,V> f = n.next;
if (n != b.next) // inconsistent read
break;
if ((v = n.value) == null) { // n is deleted
n.helpDelete(b, f);
break;
}
if (b.value == null || v == n) // b is deleted
break;
// key,
if ((c = cpr(cmp, key, n.key)) > 0) {
b = n;
n = f;
continue;
}
// key , (CAS)
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
}
// key ,
z = new Node<K,V>(key, value, n);
// CAS ,
if (!b.casNext(n, z))
break; // restart if lost race to append to b
break outer;
}
}
// ( )
int rnd = ThreadLocalRandom.nextSecondarySeed();
// 1/4
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;
// ,
if (level <= (max = h.level)) {
for (int i = 1; i <= level; ++i) //???
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
@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) // lost race to add level
break;
HeadIndex<K,V> newh = h;
Node<K,V> oldbase = h.node;
for (int j = oldLevel+1; j <= level; ++j) // head
newh = new HeadIndex<K,V>(oldbase, newh, idxs[j], j);
if (casHead(h, newh)) { // head
h = newh;
idx = idxs[level = oldLevel];
break;
}
}
}
//
splice: for (int insertionLevel = 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) {
Node<K,V> n = r.node;
// compare before deletion check avoids needing recheck
int c = cpr(cmp, key, n.key);
//q right value ,q r , q right r if (n.value == null) {
if (!q.unlink(r))
break;
r = q.right;
continue;
}
//right key ,
if (c > 0) {
q = r;
r = r.right;
continue;
}
}
// right >= key
if (j == insertionLevel) {
if (!q.link(r, t))
break; // restart
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;
}
データの削除
final V doRemove(Object key, Object value) {
if (key == null)
throw new NullPointerException();
Comparator<? super K> cmp = comparator;
outer: for (;;) {
//b key , head
for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {
Object v; int c;
if (n == null) // null, ,
break outer;
Node<K,V> f = n.next;
// ,
if (n != b.next) // inconsistent read
break;
// ,
if ((v = n.value) == null) { // n is deleted
n.helpDelete(b, f);
break;
}
if (b.value == null || v == n) // b is deleted
break;
// key, ,
if ((c = cpr(cmp, key, n.key)) < 0)
break outer;
// key,
if (c > 0) {
b = n;
n = f;
continue;
}
//value ,
if (value != null && !value.equals(v))
break outer;
//CAS null
if (!n.casValue(v, null))
break;
if (!n.appendMarker(f) || !b.casNext(n, f))
findNode(key); // retry via findNode
else {
findPredecessor(key, cmp); // clean index
if (head.right == null)
tryReduceLevel();
}
@SuppressWarnings("unchecked") V vv = (V)v;
return vv;
}
}
return null;
}