Bruce Eckel's Thinking in Java (3rd Ed.) discusses Chef/Waiters/notify re
while(conditionIsNotMet) {wait;}
I wonder if the logic in the snippet below is flawed. Assume 1 Chef thread and
2 Waiter threads. Assume 1 Restaurant class that has order object. Assume
Restaurant class will give System.exit after fixed number of orders. (1) uses
notify rather than notifyAll in case both waiters are in the synchronized block
at (4).
Assuming that I'm understanding Eckel correctly, his point is that use of a loop
at (3) safeguards situation where waiter-1 is at (2) and waiter-2 is at (5) when
the notify() is given. Eckel presumes that if waiter-1 "swoops in" [goes from
(2) to (7) directly], then waiter-2 won't escape the while loop at (3), so
mishap will be avoided.
MY QUESTION IS: With respect to above scenario, isn't it also plausible that
waiter-2 escapes to (6) after waiter-1 hits point (6), but
before waiter-1 hits point(8)? Am I misunderstanding the
limitations of the sychronized/wait/notify mechanism?
If I'm mistaken, please explain? If I'm not, what is the
simplest foolproof strategy here?
I also considered switching the ordering of the while loop at
(3) and the synchronized block at (4) [i.e. place the while loop
inside the synchronized block]. I'm pretty sure that this
strategy fails. Among other scenarios, in the time it takes
waiter-2 to go from (6) to (7), waiter-1 could go from the start
of the sychronized block to (6).
Disagreements?
class Chef extends Thread {
// ... typical members here
publicvoid run() {
while(true) {
if (restaurant.order == null) {
restaurant.order = new Order();
synchronized(restaurant) {restaurant.notify()} // (1)
}
// try { sleep(100); } catch ...
}
}
}
class Waiter extends Thread {
// ... typical members here
publicvoid run() {
while(true) { // (2)
while (restaurant.order == null) { // (3)
synchronized(restaurant) { // (4)
try { restaurant.wait() } // (5)
// catch ...
}
}
// about to grab order // (6)
// grab and deliver order (a.k.a. print message) // (7)
restaurant.order == null; // (8)
}
}
}