Java Forum / First Aid / November 2007
wait and spurious wakeups
apm35@student.open.ac.uk - 27 Nov 2007 18:29 GMT Hello,
I have two threads, one is rcving events that cause a list to have items appended, the other is going to return the list as soon as the last item is added. A special event occurs when there are no more items to add. (please dont ask why it works this way, this is due to the mandatory use of a third-party API that forces this on us). The first thread calls notify when the special event occurs, the second thread calls wait before returning the list of items.
Here is my question: what is wrong with calling wait just as wait()? The developer I am working with claims that wait suffers from the potential to experience interrupts and spuirous wakeups. Is that right? He suggested that the following code be used:
synchronized (listOwner) { while (special event not received) { listOwner.wait(); } }
Can someone explain this to me please? I have tried talking to the developer but there is a communication problem (different timezones, different languages).
I have checked the java web page http://java.sun.com/j2se/1.3/docs/api/java/lang/Object.html#wait() where it says that wait() can get InterruptedException, but that is only if another thread interrupts the current thread. There is no way that thread 1 can interrupt thread 2 that I am aware of. I wonder what is being referred to here.
-Andrew Marlow
Patricia Shanahan - 27 Nov 2007 18:37 GMT ...
> Here is my question: what is wrong with calling wait just as wait()? > The developer I am working with claims that wait suffers from the [quoted text clipped - 11 lines] > developer but there is a communication problem (different timezones, > different languages). ...
The non-looping code would be:
synchronized (listOwner) { if(special event not received) { listOwner.wait(); } }
You need to do the test inside the synchronized block to avoid race conditions where the notifying thread does its notify after the waiting thread has done its test but before it enters wait.
The difference in cost between doing the "if" and a "while" is so small, compared to the cost of a wait and inter-thread communication, that you might just as well use "while", even if you are sure "if" would be sufficient. It is more robust in the face of future changes, such as adding use of interrupts.
Patricia
Daniel Pitts - 27 Nov 2007 19:45 GMT > .... >> Here is my question: what is wrong with calling wait just as wait()? [quoted text clipped - 34 lines] > > Patricia but if is *not* sufficient. There can be spurious signals that don't mean the special flag has been set.
 Signature Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
Patricia Shanahan - 27 Nov 2007 22:08 GMT >> .... >>> Here is my question: what is wrong with calling wait just as wait()? [quoted text clipped - 37 lines] > There can be spurious signals that don't mean the special flag has been > set. The Object wait() documentation says "Causes current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object."
The structure of the program appears to exclude a spurious notify, it is not using notifyAll, and there are no Java interrupts. Under those conditions, wouldn't a spurious return from wait represent a bug in the wait implementation, a failure to conform to its API documentation?
Patricia
Daniel Pitts - 28 Nov 2007 19:02 GMT >>> .... >>>> Here is my question: what is wrong with calling wait just as wait()? [quoted text clipped - 48 lines] > > Patricia From the documentation on wait(int): "A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup. While this will rarely occur in practice, applications must guard against it by testing for the condition that should have caused the thread to be awakened, and continuing to wait if the condition is not satisfied. In other words, waits should always occur in loops, like this one:"
 Signature Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
Patricia Shanahan - 29 Nov 2007 12:54 GMT ...
> From the documentation on wait(int): > "A thread can also wake up without being notified, interrupted, or [quoted text clipped - 3 lines] > continuing to wait if the condition is not satisfied. In other words, > waits should always occur in loops, like this one:" OK, I concede it is documented, at least if one treats the "behaves like wait(0)" comment as overriding the direct description of wait(). I'm still curious about how the thread becomes runnable when there is no timer and no activity on the monitor.
Patricia
apm35@student.open.ac.uk - 29 Nov 2007 17:26 GMT > ... > [quoted text clipped - 12 lines] > > Patricia Yes, so am I. All I get is "it is something to do with the OS, read Brian's book". Well that book is well and truely on my list now, but I wonder if anyone apart from Brian actually knows the specific technical reason.
Lew - 30 Nov 2007 01:28 GMT >> ... >> [quoted text clipped - 16 lines] > wonder if anyone apart from Brian actually knows the specific > technical reason. JCIP says, on p. 300,
> "When control re-enters the code calling /wait/, it has reacquired the lock associated with the condition queue. Is the condition predicate now true? Maybe. It might have been true at the time the notifying thread called /notifyAll/, but could have become false again by the time /you/ reacquire the lock. ... Or maybe it hasn't been true at all since you called /wait/. You don't know why another thread called /notify/ or /notifyAll/; maybe it was because /another/ condition predicate associated with the same condition queue became true." (emphasis original)
All a return from wait() guarantees is that you have the lock, not that the condition has changed.
 Signature Lew
Patricia Shanahan - 30 Nov 2007 05:07 GMT >>> ... >>> [quoted text clipped - 31 lines] > All a return from wait() guarantees is that you have the lock, not that > the condition has changed. I think the true spurious wake-up question is whether wait can return without timeout or lock acquisition. In some contexts, including the one described at the start of this thread, if wait has acquired the lock then the resource is available.
In practice, I always use the "while" loop because it is definitely more robust. Using "if" breaks if the program changes in any of several ways.
My real question is whether there can be a truly spurious wake-up without a notifyAll or timeout. Is it real, or is it an urban legend?
Patricia
Eric Sosman - 30 Nov 2007 20:20 GMT >> All a return from wait() guarantees is that you have the lock, not >> that the condition has changed. [quoted text clipped - 3 lines] > described at the start of this thread, if wait has acquired the lock > then the resource is available. The object's monitor is re-acquired before the caller regains control. "Regains control" covers plain returns, returns after a time-out, and the throwing of exceptions from inside the wait call.
> In practice, I always use the "while" loop because it is definitely more > robust. Using "if" breaks if the program changes in any of several ways. > > My real question is whether there can be a truly spurious wake-up > without a notifyAll or timeout. Is it real, or is it an urban legend? The Wikipedia article quotes Butenhof as expressing some doubt about the reality of spurious wakeups (and he's certainly in a good position to know). It might turn out to be legend and FUD, after all. However, the folks who implement the synchronization primitives are by now convinced that they have a license to wake up spuriously if they ever find a good reason to do so, so today's FUD might become tomorrows fad ... It's sort of like those "Reserved for future expansion; must be zero" things you find all over the place: You might get away with stuffing non-zeroes into them, and you might even get away with it forever; anticipated expansions don't always come to pass. But sometimes they do, and then ...
comp.programming.threads is probably the right forum for pursuing this further.
 Signature Eric.Sosman@sun.com
Lew - 30 Nov 2007 23:46 GMT > comp.programming.threads is probably the right forum for pursuing > this further. I'd rather it stay here as long as we're talking about Java.
 Signature Lew
apm35@student.open.ac.uk - 27 Nov 2007 22:25 GMT On 27 Nov, 19:45, Daniel Pitts <newsgroup.spamfil...@virtualinfinity.net> wrote:
> >> Here is my question: what is wrong with calling wait just as wait()?
> There can be spurious signals that don't mean the special flag has been set. I think I have found the reason why some people say there can be spurious wakeups. I think they are right and I was wrong. The key to me understanding it is due to this web page, from Sun: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html. Here is says:
--- As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop:
synchronized (obj) { while (<condition does not hold>) obj.wait(timeout, nanos); ... // Perform action appropriate to condition } --- This text appears when discussing the two argument version and the zero argument version, i.e it applies for all flavours of wait. So it is nothing to do with whether or not timeouts are used. I am aware that the underlying operating system primitives that do timed waits can be awoken prematurely, as described by Butenhof. It is quite conceivable that this behaviour is passed on to java. But I am calling wait with no arguments and did not think the same concerns applied. The sun java page shows I was wrong. I had better go and fix my code!
-Andrew Marlow
apm35@student.open.ac.uk - 27 Nov 2007 22:01 GMT > The difference in cost between doing the "if" and a "while" is so small, > compared to the cost of a wait and inter-thread communication, that you > might just as well use "while", even if you are sure "if" would be > sufficient. It is more robust in the face of future changes, such as > adding use of interrupts. But if an interrupt happens isn't InterruptedException thrown? That exception is in the throws list for wait(). And if that happens I do want to bomb out since I do not expect it to happen (e.g the unexpected would happen if I ever ran the server interactively and hit ctrl-C when I was in the wait; don't mind bombing out then, in fact it is the right thing to do).
-Andrew M.
Eric Sosman - 27 Nov 2007 21:14 GMT > Hello, > [quoted text clipped - 27 lines] > that thread 1 can interrupt thread 2 that I am aware of. I wonder what > is being referred to here. Browse to <http://www.google.com/>, type "spurious wakeup" in the box, and click the "I'm Feeling Lucky" button. Read *all* of the Wikipedia article this takes you to, not just the part at the beginning where Butenhof says that there's no such thing. Pay special attention to the "Other reasons for verifying the invariant" section; it may not apply to your very simple situation as things stand today, but what if the next version of this third-party API grows a few new features? You may as well insure against the future, when the insurance is as cheap as writing `while' instead of `if'.
 Signature Eric Sosman esosman@ieee-dot-org.invalid
apm35@student.open.ac.uk - 27 Nov 2007 21:58 GMT > > Here is my question: what is wrong with calling wait just as wait()?
> > I have checked the java web > > where it says that wait() can get InterruptedException, but that is [quoted text clipped - 6 lines] > of the Wikipedia article this takes you to, not just the part at > the beginning where Butenhof says that there's no such thing. Done.
> Pay > special attention to the "Other reasons for verifying the invariant" > section; Here it is:
Practical reasons exist for checking the invariant after a return from a wait other than spurious wakeups. For example, a waked-up thread may not be scheduled immediately after the wake up, but be at the mercy of the system scheduler. A scheduler may preempt a process abruptly or schedule other threads. It may be the case that in the mean time, an external entity (another process, hardware) has invalidated the invariant assumption. Wrapping the wait with a loop avoids such cases.
> it may not apply to your very simple situation as things > stand today, You're right, it doesn't.
> but what if the next version of this third-party API > grows a few new features? You may as well insure against the > future, when the insurance is as cheap as writing `while' instead > of `if'. I still don't understand. The wikipedia article is actually talking about the premature wakeups that can happen when waiting on POSIX mutexes or condition variables. And these wakeups are due to system interrupts. I know these might occur in java as well but I figured this is why wait() throws InterruptedException. Well, if that happens flow of control is broken and rightly so for my app. I certainly do not want it to absorb the exception and loop round to wait again.
So that leaves the mysterious spurious wakeup that is referred to in the paragraph you mention:- "an external entity (another process, hardware) has invalidated the invariant assumption". I don't see how hardware can do it without it being handled as InterruptedException so that only leaves another process. So how can other process cause a java program to make a thread return from a wait() prematurely. I really don't see how.
Regards,
Andrew Marlow
Knute Johnson - 27 Nov 2007 22:34 GMT >>> Here is my question: what is wrong with calling wait just as wait()? > [quoted text clipped - 53 lines] > > Andrew Marlow According to Brian Goetz, Java Concurrency In Practice, "Additionally, wait is even allowed to return 'spuriously' -not in response to any thread calling notify."
And he has a list of rules for using condition waits
1 Always have a condition predicate - some test of object state that must hold before proceeding 2 Always test the condition predicate before calling wait() and again after returning from wait 3 Always call wait in a loop (my note - I guess that makes 1&2 simpler) 4 Ensure that the state variable making up the condition predicate are guarded by the lock associated with the condition queue 5 Hold the lock associated with the condition queue when calling wait, notify or notifyAll 6 Do not release the lock after checking the condition predicate but before acting on it
synchronized (lock) { while (!conditionPredicate) lock.wait(); }
And the releasing code
synchronized (lock) { conditionPredicate = true; lock.notify(); }
As to where the in the JLS spurious wakeups are allowed, I don't know.
 Signature Knute Johnson email s/nospam/knute/
Eric Sosman - 27 Nov 2007 23:18 GMT >> [...] >> Pay [quoted text clipped - 22 lines] > > I still don't understand. [...] The situation you describe is unusually simple. So simple that there seems no technical reason to use threads at all (you mention that the multi-thread framework was imposed by external forces). In your simple situation, the "wrong" way will work just fine -- but will your situation remain this simple forever?
Useful programs have a way of evolving, of extending, of finding themselves employed in new circumstances. Ponder a few of the kinds of things that might happen:
- Somebody decides that the single "supplier" thread makes poor use of his multi-core CPU, and decides to divide the work across eight suppliers in hopes of better throughput. Your condition for proceeding changes from "The supplier is no longer active" to "The count of active suppliers has gone to zero." As each supplier finishes it will call notify() just in case it was the last, and all but the last awakening will be a false alarm.
- An additional "consumer" is added, maybe to do auditing or logging or something. This consumer is also interested in the list of items, but wants to be awakened every time an item is added. Your original "accumulator" and the new consumer both wait() on the list, and the supplier now calls notifyAll() for every new item and for the "poison pill" at the end, and all but one of these is a false alarm as far as your accumulator thread is concerned.
- The same external forces that dictated threading to begin with may dictate weird changes that will require some threads to call notify() before it's really time for your accumulator to proceed. Your accumulator must be prepared to be awakened prematurely and to go back to sleep.
Here's the nub: The caller of notify() doesn't know what the caller of wait() is waiting for. That's the waiter's business, after all, expressed in the waiter's code. All the notifier needs to know is that the change it has just made to some object *may* be *part* of something another thread waits for, so it calls notify() to give the waiter a chance to make its own decision. Some of those awakenings may be "genuine" in the sense that notify() was truly called, but "spurious" in the sense that the condition being waited for does not yet hold. It's a kind of encapsulation, if you like, that limits the amount of shared knowledge that must be spread around to the many parts of your program.
Summary: Always use
synchronized(thing) { while (! readyToGo()) thing.wait(); doLockedThings(thing); } doOtherThings(thing);
... because it will always be safe, no matter what happens. In absurdly simple situations you could change `if' to `while', but why tempt Fate? In any case it is *never* correct to write
synchronized(thing) { thing.wait(); // unguarded wait is R-O-N-G! doLockedThings(thing); } doOtherThings(thing);
... and the Google phrase for this error is "lost wakeup."
 Signature Eric Sosman esosman@ieee-dot-org.invalid
apm35@student.open.ac.uk - 28 Nov 2007 11:00 GMT > Some of those awakenings may be "genuine" in the sense that notify() > was truly called, but "spurious" in the sense that the condition > being waited for does not yet hold. This is what I did not fully appreciate until I found it documented on sun's web site, for all forms of wait(), not just the ones with a timeout parameter.
> Summary: Always use > [quoted text clipped - 6 lines] > > ... because it will always be safe, no matter what happens. I will do this. But there is still something I don't quite understand. If the readyToGo() method is also synchronized on 'thing' (which it is in my case) then I dont need to call readyToGo, do I? I could access the private member directly. Another thread cannot access the variable because I am already synchronized via the line "synchronized(thing)", right?
> In any case it is *never* correct to write > [quoted text clipped - 3 lines] > } > doOtherThings(thing); This is what I was doing. I will fix it.
-Andrew
Eric Sosman - 28 Nov 2007 14:09 GMT >> [...] >> Summary: Always use [quoted text clipped - 14 lines] > because I am already synchronized via the line "synchronized(thing)", > right? The details of readyToGo() will depend on the application at hand. Sometimes it might be a simple expression involving a couple of member variables in `thing'. Sometimes it might be a method call like isEmpty(). The decision to proceed or to wait depends (presumably) on the state of `thing', and (also presumably) there are other threads that modify that state and will call notify() or notifyAll() when they do so.
The reason for synchronizing before making the test is to prevent weird things from happening if the other threads make changes while readyToGo() is in the middle of making up its mind. That's also the reason for performing doLockedThings() while synchronized: If you didn't, the changes you make could confuse the other threads.
The `synchronized' block doesn't make any tests, as such, and doesn't guarantee anything about the state of its object. All it does is give your thread exclusive access, in the sense that no other thread can synchronize on that same object until your block completes. That means (if you've programmed things properly) that no other thread will change the object's state while you're examining it, and that any changes you make while inside the block will appear to all the other threads as if they happened simultaneously.
Of course, it's possible to make misteaks. If some thread examines or alters `thing' in "open code" without `synchronized', the fact that your thread synchronizes on it is no help. This is one area where object-oriented programming makes it easier to avoid accidental race conditions: If you make all the state private to the object's class and use accessor and mutator methods to get at it, you can put all the synchronization inside the class. Then instead of writing in the Javadoc "Please be sure to synchronize before doing X," you can just provide a method that does X and always synchronizes, making it impossible for the caller to forget to do so. Even this is not a complete cure-all, but it's a big help.
 Signature Eric Sosman esosman@ieee-dot-org.invalid
Daniel Pitts - 28 Nov 2007 19:04 GMT >> Some of those awakenings may be "genuine" in the sense that notify() >> was truly called, but "spurious" in the sense that the condition [quoted text clipped - 31 lines] > > This is what I was doing. I will fix it. I think you might benefit from reading the book Java Concurrency in Practice: <http://virtualinfinity.net/wordpress/technical-book-recommendations/java-concurr ency-in-practice/>
It describes intuitively and in detail all aspects of Concurrent programming in Java.
 Signature Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
A. Bolmarcich - 27 Nov 2007 23:13 GMT > I have checked the java web page http://java.sun.com/j2se/1.3/docs/api/java/lang/Object.html#wait() > where it says that wait() can get InterruptedException, but that is > only if another thread interrupts the current thread. There is no way > that thread 1 can interrupt thread 2 that I am aware of. I wonder what > is being referred to here. If you have control over all the code executed by thread 1 and thread 2, you can control whether thread 1 interrupts thread 2. In a Java program a thread can interrupt another if it has a reference to the other thread. Here is an example program.
public class InterruptedExample implements Runnable { private static Object lock = new Object(); private static boolean ready; public void run() { synchronized(lock) { try { ready = true; lock.notify(); lock.wait(); System.out.println("run returned from wait()"); } catch(InterruptedException e) { System.out.println("run interrupted"); } } } static public void main(String[] args) { new InterruptedExample().instanceMain(args); } public void instanceMain(String[] args) { Thread threadToInterrupt = new Thread(new InterruptedExample()); threadToInterrupt.start(); synchronized(lock) { try { if (!ready) { lock.wait(); System.out.println("main returned from wait()"); } } catch(InterruptedException e) { System.out.println("main interrupted"); } finally { threadToInterrupt.interrupt(); } } } }
Because java.lang.Thread has a enumerate(Thread[]) class method, any thread can get references to all the threads of the program and invoke interrupt() on any threads.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|