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
.