Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix IllegalMonitorStateException when using wait and notify?

I have a JPanel class which starts another thread using "implements runnable". This other thread will then at various points call a method in the JPanel class which on doing so will then need to wait for the user input. I have attempted to implement it like this:

Method in JPanel class called by other thread that needs to wait:

public void methodToWait()
{
    while(conditionIsMet)
    {
        try
        {
            wait();
        }
        catch
        {
            e.printStackTrace();
        }
    }
}

Method in JPanel class that notifies on wait on user input:

public void mouseClicked(MouseEvent event)
{
    notifyAll();
}

However, upon running the application it throws a "java.lang.IllegalMonitorStateException" upon calling the wait, why is it doing this and how do I resolve the issue?

like image 818
Jason Avatar asked Mar 06 '23 06:03

Jason


1 Answers

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
}
like image 144
xingbin Avatar answered Mar 09 '23 01:03

xingbin