Reputation: 3086
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();
}
}
}
}
}
}
}
Upvotes: 1
Views: 134
Reputation: 21306
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();
Upvotes: 1
Reputation: 242686
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();
...
}
}
}
}
Upvotes: 3
Reputation: 729
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();
}
Upvotes: -1
Reputation: 133577
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
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
..
Upvotes: 0