The IllegalMonitorStateException is related to multithreading programming in Java. If we have a monitor we want to synchronize on, this exception is thrown to indicate that a thread tried to wait or to notify other threads waiting on that monitor, without owning it.
Simply put, wait() is an instance method that's used for thread synchronization. It can be called on any object, as it's defined right on java. lang. Object, but it can only be called from a synchronized block. It releases the lock on the object so that another thread can jump in and acquire a lock.
The wait() Method Simply put, calling wait() forces the current thread to wait until some other thread invokes notify() or notifyAll() on the same object. For this, the current thread must own the object's monitor.
notifyAll() wakes up all threads that are waiting on this object's monitor. A thread waits on an object's monitor by calling one of the wait methods. The awakened threads will not be able to proceed until the current thread relinquishes the lock on this object.
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.
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.
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...
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 for obj
. 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 calls thread.notify()
or thread.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 deprecated Thread.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 a CountdownLatch
instance and have the thread call await()
on the latch to pause itself. The main thread would then call countDown()
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 for Thread::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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With