Concurrent Programming in Java start method can be called again
after termination to start a new activity using the same thread'
with `However, stopped threads are not restartable.'
[Correction to conform to JLS:
Versions of the JDK from 1.02 on do not allow restart.
See the Java Language Specification, p589 for more
details.]
volatile'
with `or access is synchronized'. [Clarification.]
moveTo and shiftX
as synchronized.
[Clarification: Lack of synchronization
needlessly invites confusion about nature of example.
Even though, by the arguments in preceeding sections,
synchronization is arguably unnecessary in this class
as it stands, it would essentially always be
needed in more realistic versions of this class
containing other methods that rely on atomicity
of updates to prevent inconsistent access.]
BoundedCounterV1' with
`BoundedCounterV0'. [Typo.]
P() and V() methods
in class CountingSemaphore should be declared
as synchronized. [Inadvertent omission.]
loc_ as volatile. [Clarification:
This makes the code conform to the advice given about classes with
methods using retries.]
RWVSN.beforeRead code.
[Coding error.] It should read:
protected void beforeRead() {
synchronized(waitingReaderMonitor_) {
synchronized(this) { // test condition under synch
if (allowReader()) {
++activeReaders_;
return;
}
else
++waitingReaders_;
}
try { waitingReaderMonitor_.wait(); }
catch (InterruptedException ex) {}
}
}
wait based consructions.' [This
corrects some poor guidance. Even in schedulers, the use of
suspend/resume is almost always inferior to wait/notify.]
SchedulerVSR example (which
could encounter a missed signal in most contexts and is not
very extensible) with the following wait-based version:
public class SchedulerVSR { // generic one-at-a-time version
protected TaskQueue queue_ = new TaskQueue(); // fixed, unique
protected Task running_ = null; // currently running task
public void enter(Task t) {
synchronized (t) { // lock t in order to use wait below
for (;;) {
synchronized(this) {
if (t == running_)
return;
else if (running_ == null) {
running_ = t;
return;
}
else
queue_.put(t); // will be dequeued by done method
}
try { t.wait(); } catch (InterruptedException ex) {}
}
}
}
public void done(Task t) {
synchronized(this) {
if (t != running_)
return; // minor safeguard
else if (queue_.isEmpty()) {
running_ = null;
return;
}
else
running_ = queue_.take();
}
synchronized(running_) { running_.notifyAll();}
}
}
[Also note that if the monitor for the Task object is never used for
any other purpose, you could change the notifyAll in to
notify. You can also add code (probably to the Queue) to
ensure that a Task is never enter()ed twice. ]
Thanks to David Holmes, Moti Ben-Ari, Doug Schmidt, David Hanson, Grant Woodside, Tom May, and Joseph Bowbeer for pointing out errors.
Please send any questions or comments about this book to dl@cs.oswego.edu.