Why wait(), notify() and notifyAll() methods in Java must be called inside a synchronized method or block is a very frequently asked Java multi-threading interview question. It is very closely related to another multi-threading question Why wait(), notify() and notifyAll() methods are in Object class?
There are few points we should be aware of before going into the reasons for why wait(), notify() and notifyAll() must be called inside a synchronized method or block.
Any method or a block of code, if not qualified with the keyword synchronized can be executed by more than one thread at any given time as object's monitor(lock) is not in the picture. Where as when a method is synchronized (or there is a synchronized block) only a single thread who has acquired the object's monitor can access the code.
I hope you would have got the picture by now. Since wait() method is about thread releasing the object's lock and go to sleep where as notify/notifyAll methods are about notifying the thread(s) waiting for the object's lock. So, wait(), notify() and notifyAll() methods (as mentioned above) should be invoked on an object only when the current thread has already acquired the lock on an object.
In fact not doing so will result in java.lang.IllegalMonitorStateException.
As example suppose I have this code where I have commented the synchronized keyword and trying to call wait
while(true){ //synchronized (sharedListObj) { // While condition as mandated to avoid spurious wakeup while(sharedListObj.size() >= 1){ try { sharedListObj.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } // Putting value in the list System.out.println("Adding to queue - " + Thread.currentThread().getName() + " " + ++i); sharedListObj.add(i); //sharedListObj.notify(); // To get out of while(true) loop if(i > 4) break; //} }
This will throw exception-
Exception in thread "Producer" java.lang.IllegalMonitorStateException at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:502) at org.netjs.examples.Producer.run(InterThreadDemo.java:20) at java.lang.Thread.run(Thread.java:745)
To summarize it, wait() method tells the current thread (thread which is executing code inside a synchronized method or block) to give up monitor. Object's lock is acquired by a thread only when it is executing in a synchronized context. So it makes sense to use wait() method, which asks thread to release the lock, only in synchronized context.
Same way; when object's notify() or notifyAll() method is called, single thread (in case of notify) or all of the threads (in case of notifyAll), waiting for the object's lock change state to runnable and contend for the object's lock, and the thread that gets the lock starts execution. Here again, notify() and notifyAll() methods can inform other threads, that the object's lock can be acquired now, only if these methods are called from the synchronized object.
So these are the reasons Why wait(), notify() And notifyAll() Must be Called Inside a Synchronized Method or Block. Please do share with me if you know any other reason for doing the same.
Related Topics
You may also like-
Good explantion
ReplyDeleteThanks for the blog. But I have a doubt.
ReplyDeleteIf we make an object's method synchronous, does it acquire the lock on the entire object?
What happens in case of static variables (when I try to make a static variable synchronous/add synchronous level to a block)?
Synchronization happens on a single lock associated with the object. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block until the first thread is done with the object.
DeleteStatic synchronization happens at the class level so only a single lock is available at the class level instead of at object level. Please refer - Static Synchronization in Java Multi-Threading to know more about static synchronization.