Simple(?) synchronized() block question

N

noident

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

chins_inus

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

Patricia Shanahan

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 :( ....
synchronized(s) // changing this line to 'synchronized(this)' fixes
the problem
{
try
{
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
 
N

noident

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

Patricia Shanahan

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
 
T

Thomas Hawtin

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;
public Foo(String ss) { s = ss; }

public void run()
{
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...
}
}
}

public static void main(String[] args)
{
new Foo("abc").start();
}
}

Tom Hawtin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,812
Latest member
GracielaWa

Latest Threads

Top