ode keeps its own lock
Node(Object x, Node n) { item = x; next = n; } }
class List { protected Node head; // pointer to first node of list
// Use plain java synchronization to protect head field. // (We could instead use a Mutex here too but there is no // reason to do so.) protected synchronized Node getHead() { return head; }
boolean search(Object x) throws InterruptedException { Node p = getHead(); if (p == null) return false;
// (This could be made more compact, but for clarity of illustration, // all of the cases that can arise are handled separately.)
p.lock.acquire(); // Prime loop by acquiring first lock. // (If the acquire fails due to // interrupt, the method will throw // InterruptedException now, // so there is no need for any // further cleanup.) for (;;) { if (x.equals(p.item)) { p.lock.release(); // release current before return return true; } else { Node nextp = p.next; if (nextp == null) { p.lock.release(); // release final lock that was held return false; } else { try { nextp.lock.acquire(); // get next lock before releasing current } catch (InterruptedException ex) { p.lock.release(); // also release current if acquire fails throw ex; } p.lock.release(); // release old lock now that new one held p = nextp; } } } }
synchronized void add(Object x) { // simple prepend // The use of `synchronized' here protects only head field. // The method does not need to wait out other traversers // who have already made it past head.
head = new Node(x, head); }
// ... other similar traversal and update methods ... }
[ Introduction to this package. ]