Java Wait and Notify: Illegalmonitorstateexception

Java Wait and Notify: IllegalMonitorStateException

You can't wait() on an object unless the current thread owns that object's monitor. To do that, you must synchronize on it:

class Runner implements Runnable
{
public void run()
{
try
{
synchronized(Main.main) {
Main.main.wait();
}
} catch (InterruptedException e) {}
System.out.println("Runner away!");
}
}

The same rule applies to notify()/notifyAll() as well.

The Javadocs for wait() mention this:

This method should only be called by a thread that is the owner of this object's monitor. See the notify method for a description of the ways in which a thread can become the owner of a monitor.

Throws:

IllegalMonitorStateException – if the current thread is not the owner of this object's monitor.

And from notify():

A thread becomes the owner of the object's monitor in one of three
ways:

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

How to fix IllegalMonitorStateException when using wait and notify?

See the doc of wait, notify and notifyAll:

Thorws IllegalMonitorStateException - if the current thread is not the
owner of the object's monitor.

That means you can not call them until you have aquired the monitor lock, in other words, until you have entered the synchronized block or synchronized method(check this for more).


Another important thing is, you should synchronize on the same object.

  • When you use synchronized block with an explict object, you should call wait and notify on this object.
  • When you use synchronized method, you are implictly synchronizing on this, so you should call this.wait() and this.notify()(keyword this is not mandory).

In this case, you need create an Object as monitor lock and share it between different classes.


Compliant example:

synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}

synchronized (obj) {
... // Prepare the condition
obj.notifyAll();
}

Noncompliant example:

void waitMethod() {
wait(); // throws IllegalMonitorStateException
}

void notifyMethod() {
notify(); // throws IllegalMonitorStateException
}

Noncompliant example:

synchronized (obj1) {
while (<condition does not hold>)
obj1.wait();
... // Perform action appropriate to condition
}

synchronized (obj2) {
... // call notifyAll on obj2 will not stop the wait on obj1
obj2.notifyAll();
}

Noncompliant example:

in class1
synchronized void waitMethod() {
while(someCondition()) {
wait();
}
}

in class2
synchronized void notifyMethod() {
notify(); // call notifyAll on class2 will not stop the wait on class1
}

Java Lock Condition Wait and Notify: IllegalMonitorStateException

Note that Condition as any class in Java extends Object and hence it has the wait method inherited from Object, which I believe you calling by mistake here, the method that your meant to be calling to wait on a condition is Condition#await rather than wait.

Wait And Notify IllegalMonitorStateException Anonymous Class

On the first Thread, you call wait on an object while having its monitor (the object being this haveCoffee).

However, on the second thread, you call notify() on me, while having the monitor of haveCoffee.

This should work:

public class WaitAndNotify {

public static void main(String[] args) {

final Thread haveCoffee = new Thread() {
public void run() {
synchronized (this) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print("I am awake and ready to have coffee");
}
}
};

Thread me = new Thread() {
public void run() {
synchronized (haveCoffee) {
try {
System.out.print("I am Sleeping");
Thread.sleep(4000);
haveCoffee.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
haveCoffee.start();
me.start();
}
}

IllegalMonitorStateException on wait() call

You need to be in a synchronized block in order for Object.wait() to work.

Also, I recommend looking at the concurrency packages instead of the old school threading packages. They are safer and way easier to work with.

EDIT

I assumed you meant Object.wait() as your exception is what happens when you try to gain access without holding the objects lock.

IllegalMonitorStateException notify() and wait()

you need to be the "owner of the object's monitor" to be able to call notify on it. so far your methods are all synchronized(this), yet they call notify() on other objects (that they are not synchronized on). in other words:

synchronized(t2) {
t2.notify();
}

and

synchronized(t1) {
t1.notify();
}

for a complete explanation of monitors and synchronization in java, see here, or look for similar questions here on SO, like this one - Java Wait and Notify: IllegalMonitorStateException

IllegalMonitorStateException on notify() when synchronized on an Integer

This

private static Integer state = 0;

is equivalent to

private static Integer state = Integer.valueOf(0);

The invocation of valueOf(0) returns a reference to an Integer object, call it A.

You then do

synchronized(state) {

your thread acquires the lock on the object referenced by state, currently that is A.

You then do

state = 1;

which is equivalent to

state = Integer.valueOf(1);

which gives you a different reference to an Integer object, call it B, and assigns it to state. When you then call

state.notify();

you're invoking notify() on an object, B, for which your thread doesn't own the monitor. You can't call notify or wait on objects for which your thread doesn't own the monitor.

How to use wait and notify in Java without IllegalMonitorStateException?

To be able to call notify() you need to synchronize on the same object.

synchronized (someObject) {
someObject.wait();
}

/* different thread / object */
synchronized (someObject) {
someObject.notify();
}


Related Topics



Leave a reply



Submit