Greetings!
I am trying to make a simple thread/conncurrency example work.
What I am trying to do in the following simple code example is:
1. Start a thread
2. Make the started thread become another object's (String s) monitor
by executing a synchronized() statement
3. Call wait().
But it fails with an IllegalMonitorStateException.
If I understand the documentation correctly, I am under impression that
if the code within the synchronized() {} block is executing, the thread
is already the monitor of the object it's synchronizing on, but that
seems not to be the case :(
The following simple program fails, and I can't figure out what's
wrong. I must be missing something simple.
import java.util.*;
public class Foo extends Thread
{
private String s;
public Foo(String ss) { s = ss; }
public void run()
{
synchronized(s) // changing this line to 'synchronized(this)' fixes
the problem
{
try
{
wait();
}
catch(InterruptedException e)
{
System.err.println(e);
System.exit(1);
}
}
}
public static void main(String[] args)
{
new Foo("abc").start();
}
}
Running the above produces this:
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:474)
at Foo.run(Foo.java:14)
my java version is:
java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot(TM) Client VM (build 1.5.0_06-b05, mixed mode)
Any suggestions will be very much appreciated.
chins_inus@yahoo.com - 30 Jun 2006 03:02 GMT
Hi,
So basically u r getting this error coz u r calling wait method
implicitly on 'this' and synchronizing String s. so if u write s.wait()
it solves ur problem.
I hope it helps...
> Greetings!
> I am trying to make a simple thread/conncurrency example work.
[quoted text clipped - 53 lines]
>
> Any suggestions will be very much appreciated.
Patricia Shanahan - 30 Jun 2006 03:03 GMT
> Greetings!
> I am trying to make a simple thread/conncurrency example work.
[quoted text clipped - 8 lines]
> is already the monitor of the object it's synchronizing on, but that
> seems not to be the case :(
...
> synchronized(s) // changing this line to 'synchronized(this)' fixes
> the problem
[quoted text clipped - 3 lines]
> wait();
> }
In order to wait, you have to be in code synchronized on the object
whose wait method you are calling. You called, in effect, this.wait()
while synchronized on the string referenced by s. You must either
synchronize on this or call s.wait().
Patricia
noident@my-deja.com - 30 Jun 2006 03:16 GMT
Thank you very much to those who replied.
Of course! wait() is the Object's method, not the Thread's. My java
textbook mentioned that but didn't stress it well enough so I missed
it.
Thanks again.
Patricia Shanahan - 30 Jun 2006 03:21 GMT
> Thank you very much to those who replied.
> Of course! wait() is the Object's method, not the Thread's. My java
> textbook mentioned that but didn't stress it well enough so I missed
> it.
> Thanks again.
Note that even if the wait were somehow resolved for the thread rather
than "this", it could not tell which object to wait on. The thread can
be synchronized simultaneously on several different objects.
Patricia
Thomas Hawtin - 30 Jun 2006 16:43 GMT
> public class Foo extends Thread
Extending Thread is almost always a bad idea. If your book tells you to
do that, burn it.
> {
> private String s;
[quoted text clipped - 4 lines]
> synchronized(s) // changing this line to 'synchronized(this)' fixes
> the problem
Using a client supplied String for a lock isn't a great idea. The String
may be shared with the rest of the code in the JRE.
A handy little trick is to declare a nested or local class called Lock
with an empty body. The full name of classes are shown if you use
ctrl-\, ctrl-break, jstack or similar. A custom class name will help you
identify locks.
> {
> try
> {
> wait();
Even if the Thread was the right object to wait on, Thread is a bad
choice of lock. In Sun JVMs, Thread uses itself as a lock for internal
operations. Attempting to lock it yourself may give strange results.
You need to be careful what you synchronise on. An easy mistake is to
lock on an outer class instance, and then within in an inner class lock
on the inner class instance because this is different.
> }
> catch(InterruptedException e)
> {
> System.err.println(e);
> System.exit(1);
Seems a little extreme...
> }
> }
[quoted text clipped - 5 lines]
> }
> }
Tom Hawtin

Signature
Unemployed English Java programmer
http://jroller.com/page/tackline/