IllegalMonitorStateException on wait() call
I know this thread is almost 2 years old but still need to close this since I also came to this Q/A session with same issue...
Please read this definition of illegalMonitorException again and again...
IllegalMonitorException 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.
This line again and again says, IllegalMonitorException comes when one of the 2 situation occurs....
1> wait on an object's monitor without owning the specified monitor.
2> notify other threads waiting on an object's monitor without owning the specified monitor.
Some might have got their answers... who all doesn't, then please check 2 statements....
synchronized (object)
object.wait()
If both object are same... then no illegalMonitorException can come.
Now again read the IllegalMonitorException definition and you wont forget it again...
wait
is defined in Object
, and not it Thread
. The monitor on Thread
is a little unpredictable.
Although all Java objects have monitors, it is generally better to have a dedicated lock:
private final Object lock = new Object();
You can get slightly easier to read diagnostics, at a small memory cost (about 2K per process) by using a named class:
private static final class Lock { }
private final Object lock = new Lock();
In order to wait
or notify
/notifyAll
an object, you need to be holding the lock with the synchronized
statement. Also, you will need a while
loop to check for the wakeup condition (find a good text on threading to explain why).
synchronized (lock) {
while (!isWakeupNeeded()) {
lock.wait();
}
}
To notify:
synchronized (lock) {
makeWakeupNeeded();
lock.notifyAll();
}
It is well worth getting to understand both Java language and java.util.concurrent.locks
locks (and java.util.concurrent.atomic
) when getting into multithreading. But use java.util.concurrent
data structures whenever you can.
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.
Based on your comments it sounds like you are doing something like this:
Thread thread = new Thread(new Runnable(){
public void run() { // do stuff }});
thread.start();
...
thread.wait();
There are three problems.
As others have said,
obj.wait()
can only be called if the current thread holds the primitive lock / mutex forobj
. If the current thread does not hold the lock, you get the exception you are seeing.The
thread.wait()
call does not do what you seem to be expecting it to do. Specifically,thread.wait()
does not cause the nominated thread to wait. Rather it causes the current thread to wait until some other thread callsthread.notify()
orthread.notifyAll()
.There is actually no safe way to force a
Thread
instance to pause if it doesn't want to. (The nearest that Java has to this is the deprecatedThread.suspend()
method, but that method is inherently unsafe, as is explained in the Javadoc.)If you want the newly started
Thread
to pause, the best way to do it is to create aCountdownLatch
instance and have the thread callawait()
on the latch to pause itself. The main thread would then callcountDown()
on the latch to let the paused thread continue.Orthogonal to the previous points, using a
Thread
object as a lock / mutex may cause problems. For example, the javadoc forThread::join
says:This implementation uses a loop of
this.wait
calls conditioned onthis.isAlive
. As a thread terminates thethis.notifyAll
method is invoked. It is recommended that applications not usewait
,notify
, ornotifyAll
onThread
instances.