Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Help! with concept of wait()-->IllegalMonitorStateException

160 views
Skip to first unread message

Joseph Thomas

unread,
Jan 25, 1999, 3:00:00 AM1/25/99
to

I need help piecing together the concept of the JVM Monitor, and
thread blocking, because I'm having a hell of a time getting an
application using Swing's JOptionPane (which calls wait()) to stop
getting an

"java.lang.IllegalMonitorStateException: current thread not owner"

I've removed only the package keyword from the following short example
class:

class MonExc
{
// Constructor

MonExc()
{
};

public static void main(String[] s)
{
try
{
MonExc ME = new MonExc();

System.out.println("So far, so good...");
Thread.currentThread().wait();
System.out.println("Never made it here.");
}
catch(Exception e){
e.printStackTrace();
}

Runtime.getRuntime().exit(0);
}
} // End class MonExc

This yields the following:

So far, so good...
java.lang.IllegalMonitorStateException: current thread not owner
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:303)
at Quotlink.MonExc.main(MonExc.java:19)


From the reading I've done so far, the Monitor is like a "box" in
which only one thread can do its stuff at any given slice in time. My
understanding of wait() is that:

1. It can only be executed by the thread currently in the "box"
(owning the monitor).

2. It has the effect of giving up its lock on the box to another
thread waiting for execution.

3. Once a thread is waiting, it grabs the Monitor the next chance it
is given.

If this is true, then:

1. Why does this program throw an IllegalMonitorStateException? Just
to excecute the wait() itself, doesn't the thread wait() is running
in need to own the Monitor?

2. My understanding of JVM threads must be flawed, because it would
seem that every thread not currently owning the Monitor is actively
wating for it, making Notify() and notifyAll() redundant.

Can someone help this lost soul who has RTFM (at least, the once
currently available to him)?

TIA,
Joe


Cheryl Stocks

unread,
Jan 25, 1999, 3:00:00 AM1/25/99
to Joseph Thomas
Joseph Thomas wrote:
> 1. Why does this program throw an IllegalMonitorStateException? Just
> to excecute the wait() itself, doesn't the thread wait() is running
> in need to own the Monitor?

The way a thread gains ownership of the monitor is by executing the
wait() within a synchronized (...) {...} block. A monitor is not
necessarily associated with a thread; it is associated with an Object
(which may be a thread, of course, since threads are objects, but that
wouldn't be a typical way of doing things). I think the code you want
is probably something like:

synchronized (this) {


System.out.println("So far, so good...");

wait();
System.out.println("Wait completed.");
}

That will use the MonExc object's monitor as the basis for the
wait/notify sequence (so the notifier needs to have a reference to the
MonExc object in order to do the notification).

I recommend you read the section of Javasoft's Java Tutorial on
threads. The Java Tutorial is at:

http://java.sun.com/docs/books/tutorial/TOC.html

(I would give you a more specific url, but I can't reach that site right
now.)

cheryl

Doug Bell

unread,
Jan 25, 1999, 3:00:00 AM1/25/99
to
Joseph Thomas <em...@erols.com> wrote:

> I need help piecing together the concept of the JVM Monitor, and
> thread blocking, because I'm having a hell of a time getting an
> application using Swing's JOptionPane (which calls wait()) to stop
> getting an
>
> "java.lang.IllegalMonitorStateException: current thread not owner"
>

> . . .


>
> From the reading I've done so far, the Monitor is like a "box" in
> which only one thread can do its stuff at any given slice in time.

Yes, sort of.

First, only threads which attempt to acquire the monitor ("enter the box")
are prevented from interfering.

Second, it is important to realize that each object has its own monitor
("box"). Only threads which attempt to acquire the monitor for the same
object are restricted.


> My understanding of wait() is that:
>
> 1. It can only be executed by the thread currently in the "box"
> (owning the monitor).

Yes. You are getting the java.lang.IllegalMonitorStateException because
your program has called wait() without first "entering the box". To enter
the box you must enter a synchronized block (either a method or block) for
the object that you are going to wait() on.

Note that in your example, the object you are attempting to wait() on is
the current thread. While not illegal, this is not really the idea. (And
it is also not generally a great idea because of how Thread.join() is
implemented using the Thread object's wait()/notify() mechanism--calling
wait() on the Thread object essentially join()'s the thread.)

In the simple case, what you probably want to wait() on is the current
object. Now from a static method, there is no current object (i.e. no
'this' reference), so that doesn't fit well with your example, but probably
does fit with the real code you are trying to get working.

Think of the object you choose to wait() on as the meeting place for all
threads that want to perform the protected operation. You can use any
object as the meeting place.


> 2. It has the effect of giving up its lock on the box to another
> thread waiting for execution.

Yes. When a thread calls wait(), it is "taken out of the box" while it is
waiting and placed in the object's "waiting room". (Each object has its
own waiting room as well as its own box.) This makes the box (monitor)
available to other threads.

While a thread is in a waiting room it is unavailable for execution. That
is, it can't be selected by the thread scheduler for execution.

Note that this waiting room has room for as many threads as needed.


> 3. Once a thread is waiting, it grabs the Monitor the next chance it
> is given.

No. The wait()ing thread remains in the waiting room until one of two
things happens. (Well, more than two if you count the Thread methods
deprecated in JDK 1.1, which I'm going to ignore.)

1) The object is notify()ed by another thread. There are two flavors
of notification:
a) The object's notifyAll() method is called, in which case all
threads are removed from the waiting room.
b) The object's notify() method is called, in which case one
arbitrarily selected thread is removed from the waiting room.

Once a thread has been removed from the waiting room because of a
notification, it is available for execution. Since it was in a
synchronized block (i.e. "in the box") when it started waiting, it
must get back in the box before it can continue executing.
Therefore, the first thing a thread removed from a waiting room
does after it is selected for execution is try to grab the monitor.

2) The thread's interrupt() method is called by another thread. In
this case the wait() throws an InterruptedException. Note that
whether or not an interrupted thread has to wait for the monitor
before continuing depends on whether the InterruptedException
handler (the catch() phrase that handles the exception) is inside
or outside of the sychronized block.

Note that there is a third possibility. There are two overloaded versions
of wait() that accept a timeout value. If neither of the above things has
happened before this timeout expires then the thread is removed from the
waiting room. There is no direct means to determine if a wait() has timed
out or been notified.


> If this is true, then:
>

> 1. Why does this program throw an IllegalMonitorStateException? Just
> to excecute the wait() itself, doesn't the thread wait() is running
> in need to own the Monitor?

In your example, the call to wait() does not occur within a synchronized
block for the current thread (the current thread is the object on which you
are waiting). This is a no-no, and that's why you get the exception.


> 2. My understanding of JVM threads must be flawed, because it would
> seem that every thread not currently owning the Monitor is actively
> wating for it, making Notify() and notifyAll() redundant.

Yes. You seem to have a model that has only a single monitor.

In reading over this, I'm not sure sticking with the box and waiting room
analogies makes this explanation easier to understand or not.


Doug Bell
db...@2nu.com

Joseph Thomas

unread,
Jan 26, 1999, 3:00:00 AM1/26/99
to

Cheryl and Doug, thanks very much for your help; you've cleared the
issue up for me conceptually. As you mentioned Doug, I was thinking
in terms of a single monitor environment (apple) versus a multiple
monitor environment (orange).

As you suggested Cheryl, I looked to Sun's tutorial pages on the web
to try out some examples. However, just as in my program, even
*their* examples cause the same exception for JOptionPanes. For the
example, I tried the DialogDemo class, and the first thing I tried,
"Simple Modal Dialogs" with "Yes/No (in the L&F's words)" caused the
following dump below. Could this be because I'm working with a beta
version of both swing and jdk?

D:\java\work>java -classpath .;C:/jdk1.2beta4/lib/classes.zip;
D:/java/work;D:/java;C:/Java/swing-1.1beta3/swing.jar DialogDemo
java -classpath .;C:/jdk1.2beta4/lib/classes.zip;D:/QL/Quotlink;
D:/QL;C:/Java/swing-1.1beta3/swing.jar DialogDemo
warning: running 1.1 version of SwingUtilities
warning: running 1.1 version of SystemEventQueueUtilities
warning: running 1.1 version of SwingGraphics
warning: running 1.1 version of DebugGraphics
Exception occurred during event dispatching:


java.lang.IllegalMonitorStateException: current thread not owner

at sun.awt.windows.WDialogPeer._show(Native Method)
at sun.awt.windows.WDialogPeer.show(WDialogPeer.java:55)
at java.awt.Dialog.show(Dialog.java:287)
at javax.swing.JOptionPane.showOptionDialog(Compiled Code)
at javax.swing.JOptionPane.showConfirmDialog(JOptionPane.java:583)
at javax.swing.JOptionPane.showConfirmDialog(JOptionPane.java:556)
at javax.swing.JOptionPane.showConfirmDialog(JOptionPane.java:529)
at DialogDemo$1.actionPerformed(DialogDemo.java:102)
at javax.swing.AbstractButton.fireActionPerformed(Compiled Code)
at javax.swing.AbstractButton$ForwardActionEvents.actionPerformed(AbstractButton.java:1101)
at javax.swing.DefaultButtonModel.fireActionPerformed(Compiled Code)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:250)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:217)
at java.awt.Component.processMouseEvent(Component.java:2876)
at java.awt.Component.processEvent(Compiled Code)
at java.awt.Container.processEvent(Compiled Code)
at java.awt.Component.dispatchEventImpl(Compiled Code)
at java.awt.Container.dispatchEventImpl(Compiled Code)
at java.awt.Component.dispatchEvent(Compiled Code)
at java.awt.LightweightDispatcher.retargetMouseEvent(Compiled Code)
at java.awt.LightweightDispatcher.processMouseEvent(Compiled Code)
at java.awt.LightweightDispatcher.dispatchEvent(Compiled Code)
at java.awt.Container.dispatchEventImpl(Compiled Code)
at java.awt.Window.dispatchEventImpl(Compiled Code)
at java.awt.Component.dispatchEvent(Compiled Code)
at java.awt.EventQueue.dispatchEvent(Compiled Code)
at java.awt.EventDispatchThread.run(Compiled Code)

Doug Bell

unread,
Jan 27, 1999, 3:00:00 AM1/27/99
to

Antranig Basman wrote:

>Doug Bell wrote:
>
>> No. The wait()ing thread remains in the waiting room until one of two
>> things happens. (Well, more than two if you count the Thread methods
>> deprecated in JDK 1.1, which I'm going to ignore.)
>>
>> 1) The object is notify()ed by another thread. There are two flavors
>> of notification:
>> a) The object's notifyAll() method is called, in which case all
>> threads are removed from the waiting room.
>> b) The object's notify() method is called, in which case one
>> arbitrarily selected thread is removed from the waiting room.
>>
>> Once a thread has been removed from the waiting room because of a
>> notification, it is available for execution. Since it was in a
>> synchronized block (i.e. "in the box") when it started waiting, it
>> must get back in the box before it can continue executing.
>> Therefore, the first thing a thread removed from a waiting room
>> does after it is selected for execution is try to grab the monitor.
>

>OK - so after a notifyAll(), at most one thread can actually
>grab the monitor. All the rest will be returned to the waiting
>room.

Well, sort of. Each object actually has a box and TWO waiting rooms. One
waiting room (room A) is for threads which are explicitly wait()ing to be
notified. The other waiting room (room B) is for threads waiting to enter
the box (get the monitor.)

Say there are two threads (X and Y) in room A. When notifyAll() is called
(by thread Z), both thread X and Y are removed from room A and made
available for execution. Once one is selected (thread X), it will first
try and get the monitor. Now, since thread Z had to have the monitor in
order to call notifyAll(), thread X will only be able to get the monitor if
thread Z has released it. Let's say thread Z has released the monitor, so
thread X gets it. Now say thread Y is selected for execution before thread
X has released the monitor. Thread Y can't get the monitor, so it is
placed into room B. Threads will be removed from room B and made available
for execution as soon as thread X releases the monitor. Whnever one of
these threads is selected for execution, it will have to try and get the
monitor again before it can execute.


>Can you explain any functional difference between
>notify() and notifyAll() - what effects could be observed by
>the programmer as a result of this brief waking and contention
>for the monitor? And which of those effects could be of potential
>use to him?

notify() is considerably more efficient than notifyAll() if several threads
are waiting. Since, as you observed and I explained, only one thread can
get the monitor, there can be some wasted effort moving threads between
rooms and trying to get the monitor. These operations have a cost, which
can impact certain designs.

However, using notify() requires a more careful design. If the thread that
gets selected to be removed from the waiting room doesn't cause notify() to
be called, the other threads may get abandoned in the waiting room and
never made available for execution. So unless your design specifically
anticipates using notify(), you should always use notifyAll().


Doug Bell
db...@2nu.com

Antranig Basman

unread,
Jan 27, 1999, 3:00:00 AM1/27/99
to Doug Bell
[mailed and posted also]

Doug Bell wrote:
>
> Antranig Basman wrote:

Thanks - mind if I test my understanding of this with a question?

> >OK - so after a notifyAll(), at most one thread can actually
> >grab the monitor. All the rest will be returned to the waiting
> >room.
>
> Well, sort of. Each object actually has a box and TWO waiting rooms. One
> waiting room (room A) is for threads which are explicitly wait()ing to be
> notified. The other waiting room (room B) is for threads waiting to enter
> the box (get the monitor.)
>
> Say there are two threads (X and Y) in room A. When notifyAll() is called
> (by thread Z), both thread X and Y are removed from room A and made
> available for execution. Once one is selected (thread X), it will first
> try and get the monitor. Now, since thread Z had to have the monitor in
> order to call notifyAll(), thread X will only be able to get the monitor if
> thread Z has released it. Let's say thread Z has released the monitor, so
> thread X gets it. Now say thread Y is selected for execution before thread
> X has released the monitor. Thread Y can't get the monitor, so it is
> placed into room B. Threads will be removed from room B and made available
> for execution as soon as thread X releases the monitor. Whnever one of
> these threads is selected for execution, it will have to try and get the
> monitor again before it can execute.

OK, as I see it, this expands the possible configurations of threads
from what I understood before.

I thought that there were three possible conditions:
i) owning the monitor, and running code in a synchronized{} block.
ii) owning the monitor, but wait()ing at a wait statement so not running.
iii) not owning the monitor, and blocking at the head of a synchronized{}
block waiting for it to become free.

So what you are saying is that iii) is expanded, so that a thread may

iv) not own the monitor, and block at a different position waiting for it,
i.e. immediately after a wait() statement, after being one of the
threads wakened by notifyAll() but not being given the monitor?

> >Can you explain any functional difference between
> >notify() and notifyAll() - what effects could be observed by
> >the programmer as a result of this brief waking and contention
> >for the monitor? And which of those effects could be of potential
> >use to him?
>
> notify() is considerably more efficient than notifyAll() if several threads
> are waiting. Since, as you observed and I explained, only one thread can
> get the monitor, there can be some wasted effort moving threads between
> rooms and trying to get the monitor. These operations have a cost, which
> can impact certain designs.

OK, since I (think I) understand the effect of notifyAll() as explained
above, this other question of mine is weakened - I can see what use
this would be to the programmer since the effects are completely
different; after thread X leaves the block, Y is available to run with
notifyAll(), and not with notify(). Check?


(Is it OK if he leaves the block after us?
Yes!
Nobody, must be asked, by me, to leave the block....! no no, Nobody etc.)

> However, using notify() requires a more careful design. If the thread that
> gets selected to be removed from the waiting room doesn't cause notify() to
> be called, the other threads may get abandoned in the waiting room and
> never made available for execution. So unless your design specifically
> anticipates using notify(), you should always use notifyAll().

Thanks - is it OK if I whip up an entry for the FAQ about this? You
do it yourself if you've got the time.

Antranig.

Doug Bell

unread,
Jan 27, 1999, 3:00:00 AM1/27/99
to
Antranig Basman wrote:

> OK, as I see it, this expands the possible configurations of threads
> from what I understood before.
>
> I thought that there were three possible conditions:
> i) owning the monitor, and running code in a synchronized{} block.
> ii) owning the monitor, but wait()ing at a wait statement so not running.
> iii) not owning the monitor, and blocking at the head of a synchronized{}
> block waiting for it to become free.
>
> So what you are saying is that iii) is expanded, so that a thread may
>
> iv) not own the monitor, and block at a different position waiting for it,
> i.e. immediately after a wait() statement, after being one of the
> threads wakened by notifyAll() but not being given the monitor?

Yes to state iv, no to state ii. When a thread is wait()ing, it does not
own the monitor. The monitor is released before the thread "enters the
waiting room". State ii is:

ii) wait()ing at a wait() statement so not running

Basically there are four states for a thread:

initial: After a thread is created but before it is start()ed
it is in the initial state.
runnable: Once a thread is start()ed, it is in the runnable state
until either the corresponding run() method exits or
the thread is suspended or blocked. run() can exit
either normally, or from an uncaught exception or error.
This state has two possibilities:
1) The thread is executing.
2) The thread is waiting to be selected for execution.
blocked: When a thread is suspended or blocked it is in the
blocked state. This state has three possibilities:
1) The thread is wait()ing for an object to be
notify()ed.
2) The thread is blocked waiting for an object's
monitor so that it can enter a synchronized
block.
3) The thread is suspend()ed, waiting to be
resume()d. (Note that suspend() and resume()
are deprecated as of JDK 1.2.)
exitting: After the run() method exits, the thread is in the
exitting state.


> > notify() is considerably more efficient than notifyAll() if several threads
> > are waiting. Since, as you observed and I explained, only one thread can
> > get the monitor, there can be some wasted effort moving threads between
> > rooms and trying to get the monitor. These operations have a cost, which
> > can impact certain designs.
>
> OK, since I (think I) understand the effect of notifyAll() as explained
> above, this other question of mine is weakened - I can see what use
> this would be to the programmer since the effects are completely
> different; after thread X leaves the block, Y is available to run with
> notifyAll(), and not with notify(). Check?

Yes.


> > However, using notify() requires a more careful design. If the thread that
> > gets selected to be removed from the waiting room doesn't cause notify() to
> > be called, the other threads may get abandoned in the waiting room and
> > never made available for execution. So unless your design specifically
> > anticipates using notify(), you should always use notifyAll().
>
> Thanks - is it OK if I whip up an entry for the FAQ about this? You
> do it yourself if you've got the time.

Tell you what, how about you write the entry and I'll look it over.


Doug Bell
db...@2nu.com

Doug Bell

unread,
Jan 27, 1999, 3:00:00 AM1/27/99
to
Doug Bell quickly and incompletely wrote:

> blocked: When a thread is suspended or blocked it is in the
> blocked state. This state has three possibilities:
> 1) The thread is wait()ing for an object to be
> notify()ed.
> 2) The thread is blocked waiting for an object's
> monitor so that it can enter a synchronized
> block.
> 3) The thread is suspend()ed, waiting to be
> resume()d. (Note that suspend() and resume()
> are deprecated as of JDK 1.2.)

There is an obvious fourth possibility I omitted:

4) The thread is sleep()ing.


Doug Bell
db...@2nu.com

A.M. Basman

unread,
Jan 28, 1999, 3:00:00 AM1/28/99
to Doug Bell
Doug Bell wrote:
>
> Doug Bell quickly and incompletely wrote:
[]

> initial: After a thread is created but before it is start()ed
> it is in the initial state.
> runnable: Once a thread is start()ed, it is in the runnable state
> until either the corresponding run() method exits or
> the thread is suspended or blocked. run() can exit
> either normally, or from an uncaught exception or error.
> This state has two possibilities:
> 1) The thread is executing.
> 2) The thread is waiting to be selected for execution.
> blocked: When a thread is suspended or blocked it is in the
> blocked state. This state has three possibilities:
> 1) The thread is wait()ing for an object to be
> notify()ed.
> 2) The thread is blocked waiting for an object's
> monitor so that it can enter a synchronized
> block.
> 3) The thread is suspend()ed, waiting to be
> resume()d. (Note that suspend() and resume()
> are deprecated as of JDK 1.2.)
> exitting: After the run() method exits, the thread is in the
> exitting state.

> There is an obvious fourth possibility I omitted:


>
> 4) The thread is sleep()ing.

Wait, wait! (no pun intended). This list doesn't explicitly
list the state iv) that I mentioned - that is, is the state
of a thread notifyAll()ed but not having the monitor part
of runnable 2) or blocked 2)?. If the latter, it isn't
really "waiting to enter a synchronized block" since it's
already in one... perhaps "waiting to reenter one".

I find that to someone who doesn't know the underlying reality,
it's extremely difficult to express what Java threads are up
to in a way not subject to misinterpretation. Even explaining
wait/notify is botched around 1/3 of the time. notifyAll I
have *never* seen a convincing explanation of.. (sorry, Peter!) :)

BTW, are there technical terms for "waiting room A" for
blocked threads, and "waiting room B" for waiting threads?

Sorry to keep pestering you like this,

Antranig.

>>
>> Thanks - is it OK if I whip up an entry for the FAQ about this? You
>> do it yourself if you've got the time.
>
>Tell you what, how about you write the entry and I'll look it over.

OK, will do. I should be uniquely qualified to explain this,
through being uniquely resistant to understanding it :)

Kevin Kelley

unread,
Jan 28, 1999, 3:00:00 AM1/28/99
to
"A.M. Basman" <am...@eng.cam.ac.uk> wrote:


The confusion for me was in realizing that, although the wait()
is textually _inside_ a synchronized block, while the thread is
wait()ing it does _not_ have the monitor: so executing a wait()
can be thought of as taking you back outside the synchronized
block, and you can't get back in until you reacquire the monitor.

So when a thread executes a wait() statement it changes state
from runnable to blocked: subitem 1), wait()ing for a notify().
When the notify() happens somewhere else, it changes to blocked:
subitem 2), not on the wait() list but still waiting to acquire
the monitor.

So there's two lists: explicitly wait()ing for a notify(), and
been notify()ed but still waiting to acquire the monitor so it
can actually run.


--
Kevin Kelley http://www.ruralnet.net/~kelley/
Starlight Software Co. http://www.kevin-kelley.com/

Doug Bell

unread,
Jan 28, 1999, 3:00:00 AM1/28/99
to
"A.M. Basman" <am...@eng.cam.ac.uk> wrote:

> Doug Bell wrote:
> >
> > initial: After a thread is created but before it is start()ed
> > it is in the initial state.
> > runnable: Once a thread is start()ed, it is in the runnable state
> > until either the corresponding run() method exits or
> > the thread is suspended or blocked. run() can exit
> > either normally, or from an uncaught exception or error.
> > This state has two possibilities:
> > 1) The thread is executing.
> > 2) The thread is waiting to be selected for execution.
> > blocked: When a thread is suspended or blocked it is in the
> > blocked state. This state has three possibilities:
> > 1) The thread is wait()ing for an object to be
> > notify()ed.
> > 2) The thread is blocked waiting for an object's
> > monitor so that it can enter a synchronized
> > block.
> > 3) The thread is suspend()ed, waiting to be
> > resume()d. (Note that suspend() and resume()
> > are deprecated as of JDK 1.2.)

> > 4) The thread is sleep()ing.

> > exitting: After the run() method exits, the thread is in the
> > exitting state.
>

> Wait, wait! (no pun intended). This list doesn't explicitly
> list the state iv) that I mentioned - that is, is the state
> of a thread notifyAll()ed but not having the monitor part
> of runnable 2) or blocked 2)?. If the latter, it isn't
> really "waiting to enter a synchronized block" since it's
> already in one... perhaps "waiting to reenter one".

After the thread is notified it is in the runnable state waiting to be
selected for execution. Once it is selected for execution the first thing
it will do is attempt to enter the monitor for the object it had been
waiting on. If it can't enter the monitor it will then be blocked waiting
for the object's monitor.

As to calling this "waiting to reenter the synchronized block", I suppose.
However, it's not really another state. The state is that the thread is
waiting to enter the object's monitor. The clause "so that it can enter a
synchronized block" was simply added to make the state easier to identify
for someone unsure of what it means to be "waiting for an object's
monitor".

I can make a case for a different additional possibility for a blocked thread:

5) The thread has join()ed another thread.

The reason I didn't include this as a separate state initially, although on
reflection perhaps I should to be complete, is that join() uses the
wait()/notify() mechanism. That is to say that join()ing a thread wait()s
on the Thread object. When a thread terminates, notifyAll() is called on
the Thread object. Since join() is part of the public interface for
Threads and the wait()/notify() mechansim used by join() is part of the
hidden implementation, join() probably deserves its own item in the list.


> BTW, are there technical terms for "waiting room A" for
> blocked threads, and "waiting room B" for waiting threads?

Not that I've seen.


Doug Bell
db...@2nu.com

David Holmes

unread,
Feb 2, 1999, 3:00:00 AM2/2/99
to
A.M. Basman wrote in message <36B079...@eng.cam.ac.uk>...

>I find that to someone who doesn't know the underlying reality,
>it's extremely difficult to express what Java threads are up
>to in a way not subject to misinterpretation. Even explaining
>wait/notify is botched around 1/3 of the time. notifyAll I
>have *never* seen a convincing explanation of.. (sorry, Peter!) :)


Unfortunately even this thread has not been completely accurate or
particularly clear in describing what happens.

First clarification. Before a thread can return from wait() it must
reacquire the monitor for the object whose wait-set it was waiting in. This
occurs no matter why the thread returned:
- notification (notify() or notifyAll() )
- time-out (if applicable)
- spurious wakeup
- interruption

In the case of interruption, if the InterruptedException is caught outside
of the synchronized block then, of course, by then the monitor has been
released again *but* it still had to be acquired first. Now it may be
possible for an implementation to optimise this so that it only reacquires
the monitor if the InterruptedException is caught within the synchronized
block but the JDK certainly doesn't do this and it is probably not a good
idea in general because without the re-entry of the monitor you won't get
the necessary memory-synchronisation behaviour (ref. Ch17 of the Java
Language Specification)

Now as to the difference between notify() and notifyAll() it is very simple:
notify() removes at most one thread from the wait-set (ie. allows one thread
to return from wait() ), whilst notifyAll() removes all threads from the
wait-set. Reasons to use either of these depend on why your are waiting. If
all threads wait() for the same condition to be true *and* only one thread
can benefit from that condition being true - then use notify(). For example,
if you write your own Mutex class you would use notify(). However, if all
threads wait() for the same condition and that condition enables all the
threads to continue then use notifyAll(). For example a Barrier holds up all
threads until the last one gets there - thus notifyAll() is performed by the
last thread arriving. If the threads are waiting for different conditions,
such as a bounded buffer being full, or a bounded buffer being empty then
you must use notifyAll() otherwise you won't know which thread gets notified
and if the wrong thread gets notified it will simply check its condition,
see that it hasn't changed and wait() again, leaving the 'right' thread in
the wait-set even though it could continue.

Take a look at Doug Lea's book "Concurrent Programming in Java" and the
material on his website: http://gee.cs.oswego.edu/dl/cpj/


David

0 new messages