Simple(?) synchronized() block question

Discussion in 'Java' started by noident@my-deja.com, Jun 30, 2006.

  1. Guest

    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.
     
    , Jun 30, 2006
    #1
    1. Advertising

  2. Guest

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


    wrote:
    > 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.
     
    , Jun 30, 2006
    #2
    1. Advertising

  3. wrote:
    > 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
     
    Patricia Shanahan, Jun 30, 2006
    #3
  4. Guest

    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.
     
    , Jun 30, 2006
    #4
  5. wrote:
    > 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
     
    Patricia Shanahan, Jun 30, 2006
    #5
  6. wrote:
    > 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
    --
    Unemployed English Java programmer
    http://jroller.com/page/tackline/
     
    Thomas Hawtin, Jun 30, 2006
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jerry
    Replies:
    4
    Views:
    132,054
    tonni
    Aug 11, 2010
  2. Pep
    Replies:
    6
    Views:
    29,367
  3. dmcreyno
    Replies:
    9
    Views:
    9,626
    Mark Space
    Jun 27, 2006
  4. grz01
    Replies:
    9
    Views:
    3,462
    Andreas Leitgeb
    Sep 22, 2008
  5. ankur
    Replies:
    4
    Views:
    1,512
    Eric Sosman
    Nov 28, 2008
Loading...

Share This Page