However, if the last philosopher is initialized to
try to get the right chopstick first, and then the left, then that philosopher
will never prevent the philosopher on the immediate left from picking up
their right chopstick, and so the circular wait is prevented. This is only
one solution to the problem, but you could also solve it by preventing one
of the other conditions (see more advanced threading books for more
details). Feedback
There is no Java language support to help prevent deadlock; it’s up to you
to avoid it by careful design. These are not comforting words to the person
who’s trying to debug a deadlocking program. Feedback
The proper way to stop
One change that was introduced in Java 2 to reduce the possibility of
deadlock is the deprecation of the Thread class’ stop( ), suspend( ), and resume( ) methods. Feedback
The reason that the stop( ) method is deprecated is because it doesn’t
release the locks that the thread has acquired, and if the objects are in an
inconsistent state (“damaged”) other threads can view and modify them in
that state. The resulting problems can be subtle and difficult to detect.
Instead of using stop( ), you should use a flag to tell the thread when to
terminate itself by exiting its run( ) method. Here’s a simple example:
Feedback
//: c13:Stopping.java
// The safe way to stop a thread.
import java.util.*;
class CanStop extends Thread {
// Must be volatile:
private volatile boolean stop = false;
private int counter = 0;
public void run() {
while(!stop && counter < 10000) {
System.out.println(counter++);
}
if(stop)
770
Thinking in Java
www.BruceEckel.com
System.out.println("Detected stop");
}
public void requestStop() { stop = true; }
}
public class Stopping {
public static void main(String[] args) {
final CanStop stoppable = new CanStop();
stoppable.start();
new Timer(true).schedule(new TimerTask() {
public void run() {
System.out.println("Requesting stop");
stoppable.requestStop();
}
}, 500); // run() after 500 milliseconds
}
} ///:~
The flag stop must be volatile so that the run( ) method is sure to see it (otherwise the value may be cached locally). The “job” of this thread is to
print out 10,000 numbers, so it is finished whenever counter >= 10000
or someone requests a stop. Note that requestStop( ) is not
synchronized because stop is both boolean (changing it to true is an atomic operation) and volatile. Feedback
In main( ), a CanStop object is started, then a Timer is set up to call requestStop( ) after ½ second. The constructor for Timer is passed the
argument true to make it a daemon thread, so that it doesn’t prevent the
program from terminating. Feedback
Interrupting a blocked
thread
There are times when a thread blocks—such as when it is waiting for
input—and it cannot poll a flag as it does in the previous example. In
these cases, you can use the Thread. interrupt( ) method to break out of
the blocked code: Feedback
//: c13:Interrupt.java
// Using interrupt() to break out of a blocked thread.
Chapter 13: Concurrency
771
import java.util.*;
class Blocked extends Thread {
public Blocked() {
System.out.println("Starting Blocked");
start();
}
public void run() {
try {
synchronized(this) {
wait(); // Blocks
}
} catch(InterruptedException e) {
System.out.println("Interrupted");
}
System.out.println("Exiting run()");
}
}
public class Interrupt {
static Blocked blocked = new Blocked();
public static void main(String[] args) {
new Timer(true).schedule(new TimerTask() {
public void run() {
System.out.println("Preparing to interrupt");
blocked.interrupt();
blocked = null; // to release it
}
}, 2000); // run() after 2000 milliseconds
}
} ///:~
The wait( ) inside Blocked.run( ) produces the blocked thread. When
the Timer runs out, the object’s interrupt( ) method is called. Then the
blocked reference is set to null so the garbage collector will clean it up
(not necessary here, but important in a long-running program). Feedback
772
Thinking in Java
www.BruceEckel.com
Thread groups
A Thread Group holds a collection of threads. The value of thread groups
can be summed up by a quote from Joshua Bloch5, the software architect
at Sun who fixed and greatly improved the Java collections library in JDK
1.2: Feedback
“Thread groups are best viewed as an unsuccessful experiment, and
you may simply ignore their existence.”
If you’ve spent time and energy trying to figure out the value of thread
groups (as I have), you may wonder why there was not some more official
announcement from Sun on the topic, sooner than this (the same
question could be asked about any number of other changes that have
happened to Java over the years). The Nobel Laureate economist Joseph
Stiglitz has a philosophy of life which would seem to apply here6. It’s
called The Theory of Escalating Commitment: Feedback