// This example is from the book _Java Threads_ by Scott Oaks and Henry Wong.
// Written by Scott Oaks and Henry Wong.
// Copyright (c) 1997 O'Reilly & Associates.
// You may study, use, modify, and distribute this example for any purpose.
// This example is provided WITHOUT WARRANTY either expressed or implied.
// Sample Reader-Writer Lock, Chapter 7, p. 182.
class RWNode {
static final int READER = 0;
static final int WRITER = 1;
Thread t;
int state;
int nAcquires;
RWNode(Thread t, int state) {
this.t = t;
this.state = state;
nAcquires = 0;
}
}
public class RWLock {
private Vector waiters;
private int firstWriter() {
Enumeration e;
int index;
for (index = 0, e = waiters.elements();
e.hasMoreElements(); index++) {
RWNode node = (RWNode) e.nextElement();
if (node.state == RWNode.WRITER)
return index;
}
return Integer.MAX_VALUE;
}
private int getIndex(Thread t) {
Enumeration e;
int index;
for (index = 0, e = waiters.elements();
e.hasMoreElements(); index++) {
RWNode node = (RWNode) e.nextElement();
if (node.t == t)
return index;
}
return -1;
}
public RWLock() {
waiters = new Vector();
}
public synchronized void lockRead() {
RWNode node;
Thread me = Thread.currentThread();
int index = getIndex(me);
if (index == -1) {
node = new RWNode(me, RWNode.READER);
waiters.addElement(node);
}
else node = (RWNode) waiters.elementAt(index);
while (getIndex(me) > firstWriter()) {
try {
wait();
} catch (Exception e) {}
}
node.nAcquires++;
}
public synchronized void lockWrite() {
RWNode node;
Thread me = Thread.currentThread();
int index = getIndex(me);
if (index == -1) {
node = new RWNode(me, RWNode.WRITER);
waiters.addElement(node);
}
else {
node = (RWNode) waiters.elementAt(index);
if (node.state == RWNode.READER)
throw new IllegalArgumentException("Upgrade lock");
node.state = RWNode.WRITER;
}
while (getIndex(me) != 0) {
try {
wait();
} catch (Exception e) {}
}
node.nAcquires++;
}
public synchronized void unlock() {
RWNode node;
Thread me = Thread.currentThread();
int index;
index = getIndex(me);
if (index > firstWriter())
throw new IllegalArgumentException("Lock not held");
node = (RWNode) waiters.elementAt(index);
node.nAcquires--;
if (node.nAcquires == 0)
waiters.removeElementAt(index);
notifyAll();
}
}
|