Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / First Aid / November 2007

Tip: Looking for answers? Try searching our database.

wait and spurious wakeups

Thread view: 
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 Magazines

Get 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 ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.