IllegalMonitorStateException
Explore the causes of IllegalMonitorStateException in Java concurrency and learn how to avoid this common runtime error by properly synchronizing wait and notify calls on object monitors or Condition locks. This lesson helps you understand correct synchronization techniques vital for stable multithreaded applications.
We'll cover the following...
If you are interviewing, consider buying our number#1 course for Java Multithreading Interviews.
Explanation
The IllegalMonitorStateException is a common programming error that can show up in concurrent programs. Depending on the structure of the program, the exception may occur consistently or only occasionally. The IllegalMonitorStateException exception class extends the RuntimeException class and according to the official documentation is thrown to indicate that a thread has attempted to wait on an object’s monitor or to notify other threads waiting on an object’s monitor without owning the specified monitor. In other words if you invoke wait() or notify()/notifyAll() without synchronizing on the object i.e. outside of a synchronized method or block (with the object as the synchronization target) then IllegalMonitorStateException will be thrown. Similarly, the exception is thrown when you invoke these methods on an instance of Condition class without acquiring the associated lock with the condition. The class is part of the java.lang package and not java.util.concurrent.*.
Repro using Lock
The program below demonstrates generating IllegalMonitorStateException using a Condition object that was instantiated from a Lock object.
The fix for the above program appears below:
// acquire the associated lock
lock.lock();
try {
while (/* some condition */) {
// always invoke await or wait in a loop to cater for spurious wake-ups
// and after synchronizing on the associated lock
condition.await();
}
} finally {
// remember to unlock in a finally block
lock.unlock();
}
Repro using object
The program in the widget below causes IllegalMonitorStateException by invoking notifyAll() on an object without synchronizing on it.
The fix for the above program appears below:
Object myObject = new Object();
synchronized (myObject) {
// invoking notifyAll() in a block synchronized on myObject
myObject.notifyAll();
}
Consider the program below and state the outcome of executing the main() method.
public class IllegalMonitorStateQuiz {
synchronized void someFunction() throws InterruptedException {
this.wait();
}
public static void main(String[] args) throws Exception {
(new IllegalMonitorStateQuiz()).someFunction();
}
IllegateMonitorStateException is thrown.
InterruptedException is thrown.
Program is either blocked on wait() forever or exits because of a spurious wakeup.
The target of synchronized and the object invoking wait() are different and the program doesn’t compile.