views:

52

answers:

4
public class ThreadTest
{
 public static Integer i = new Integer(0);

 public static void main(String[] args) throws InterruptedException
 {
  ThreadTest threadTest = new ThreadTest();
  Runnable odd = threadTest.new Numbers(1, "thread1");
  Runnable even = threadTest.new Numbers(0, "thread2");
  ((Thread) odd).start();
  ((Thread) even).start();
 }

 class Numbers extends Thread
 {
  int reminder;
  String threadName;

  Numbers(int reminder, String threadName)
  {
   this.reminder = reminder;
   this.threadName = threadName;
  }

  @Override
  public void run()
  {
   while (i < 20)
   {
    synchronized (i)
    {
     if (i % 2 == reminder)
     {
      System.out.println(threadName + " : " + i);
      i++;
      i.notify();
     }
     else
     {
      try
      {
       i.wait();
      }
      catch (InterruptedException e)
      {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }
     }
    }
   }
  }
 }
}
A: 

You cannot put wait() and notify() in the same synchronized block because that will just cause a deadlock. Make sure only the wait and notify functions are wrapped with a synchronized block like this:

synchronized (i) {
    i.wait(); // or i.notify();
}
Meher
A: 

As documentation states the exception is thrown when

the current thread is not the owner of the object's monitor

It also states that

This method should only be called by a thread that is the owner of this object's monitor.

And this condition can be obtained by

  • By executing a synchronized instance method of that object.
  • By executing the body of a synchronized statement that synchronizes on the object.
  • For objects of type Class, by executing a synchronized static method of that class.

You could try calling the wait method from inside the class that uses i. This could be done by extending the class and writing two new methods for notify and wait..

Jack
+3  A: 

You can't synchronize on i because it changes during execution of your program.

Since Integer in Java is immutable, after executing i++ i will contain a reference to another object, not the object you have synchronized on. So, you can't call wait()/notify() on this new object, because these methods may be only called on the object you are synchronized on, otherwise you get IllegalMonitorStateException.

You need to synchronize on some other object that doesn't change during execution. For example, you may create a separate object for this purpose:

public class ThreadTest { 
    public static Integer i = new Integer(0); 
    public static Object lock = new Object();
    ...
    class Numbers extends Thread { 
        ...
        @Override 
        public void run() { 
             ...
             synchronized (lock) {
                 ...
                 lock.notify();
                 ...
                 lock.wait();
                 ...
             }
        }
    }
}
axtavt
+1, beat me to it :)
SimonJ
thanks really gelped me a lot
Ajay
+1  A: 

This line:

i++;

is equivalent to:

i = i + 1;

which (due to autoboxing) becomes something like:

i = new Integer(i.intValue() + 1);

So, when you call i.notify() you are synchronized on the old i, not the new one.

I'd suggest changing i into an ordinary int variable, and create a separate object to synchronize on:

static int i = 0;
static Object iMonitor = new Object();
SimonJ
thanks for ur reply .. really helped me
Ajay