Skiplists and balanced search
Prev: Concurrent hashing and natural parallelism Next: Priority Queues
Exercises
Exercise 14.1. Recall that a skiplist is a probabilistic data
structure. Although the expected performance of a contains() call is
, where is the number of items in the list, the
worst-case performance could be . Draw a picture of an
eight-element skiplist with worst-case performance, and explain how it
got that way.
Exercise 14.2. You are given a skiplist with probability and
MAX_LEVEL . If the list contains nodes, what is the
expected number of nodes at each level from to ?
Exercise 14.3. Modify the LazySkipList class so find() starts at
the level of the highest node currently in the structure, instead of
the highest level possible, MAX_LEVEL.
Exercise 14.4. Modify the LazySkipList to support multiple items with
the same key.
Exercise 14.5. Suppose we modify the LockFreeSkipList class so that
on line 102 of Fig. 14.12, remove() restarts the main loop instead
of returning false.
Is the algorithm still correct? Address both safety and liveness
issues. That is, what is an unsuccessful remove() call’s new
linearization point, and is the class still lock-free?
Exercise 14.6. Explain how in the LockFreeSkipList class a node might
end up in the list at levels 0 and 2, but not at level 1. Draw
pictures.
Exercise 14.7. Modify the LockFreeSkipList so that the find()
method snips out a sequence of marked nodes with a single
compareAndSet(). Explain why your implementation cannot remove a
concurrently inserted unmarked node.
Exercise 14.8. Will the add() method of the LockFreeSkipList work
even if the bottom level is linked and then all other levels are linked
in some arbitrary order? Is the same true for the marking of the next
references in the remove() method; the bottom-level next reference
is marked last, but references at all other levels are marked in an
arbitrary order?
Exercise 14.9. (Hard) Modify the LazySkipList so that the list at
each level is bidirectional, and allows threads to add and remove items
in parallel by traversing from either the head or the tail.
Exercise 14.10. Figure 14.17 shows a buggy contains() method for the
LockFreeSkipList class. Give a scenario where this method returns a
wrong answer.
Hint: The reason this method is wrong is that it takes into account keys of nodes that have been removed.
boolean contains(T x) {
int bottomLevel = 0;
int key = x.hashCode();
Node<T> pred = head;
Node<T> curr = null;
for (int level = MAX_LEVEL; level >= bottomLevel; level--) {
curr = pred.next[level].getReference();
while (curr.key < key) {
pred = curr;
curr = pred.next[level].getReference();
}
}
return curr.key == key;
}Prev: Concurrent hashing and natural parallelism Next: Priority Queues