Friday, May 20, 2011

Why wait notify and notifyAll called from synchronized block or method in Java


Why wait (), notify () and notifyAll () must be called from synchronized block or method in Java

Why wait(), notify() and notifyAll() method must be called from synchronized block or method in JavaMost of Java developer knows that wait() ,notify() and notifyAll() method of object class must have to be called inside synchronized method or synchronized block in Java but how many times we thought why ? Recently this questions was asked to in Java interview to one of my friend, he pondered for a moment and replied that if we don't call wait () or notify () method from synchronized context we will receive IllegalMonitorStateException in java. He was right in terms of behavior of language but as per him interviewer was not completely satisfied with the answer and wanted to explain more about it. After the interview he discussed the same questions with me and I thought he might have told about race condition between wait () and notify () in Java that could exists if we don't call them inside synchronized method or block. Let’s see how it could happen:



We use wait () and notify () or notifyAll () method mostly for inter-thread communication. One thread is waiting after checking a condition e.g. In Producer Consumer example Producer Thread is waiting if buffer is full and Consumer thread notify Producer thread after he creates a space in buffer by consuming an element. calling notify() or notifyAll() issues a notification to a single or multiple thread that a condition has changed and once notification thread leaves synchronized block , all the threads which are waiting fight for object lock on which they are waiting and lucky thread returns from wait() method after reacquiring the lock and proceed further. Let’s divide this whole operation in steps to see a possibility of race condition between wait () and notify () method in Java, we will use Produce Consumer thread example to understand the scenario better:

   1. The Producer thread tests the condition (buffer is full or not) and confirms that it must wait (after finding buffer is full).
   2. The Consumer thread sets the condition after consuming an element from buffer.
   3. The Consumer thread calls the notify () method; this goes unheard since the Producer thread is not yet waiting.
   4. The Producer thread calls the wait () method and goes into waiting state.

So due to race condition here we potential lost a notification and if we use buffer or just one element Produce thread will be waiting forever and your program will hang.

Now let's think how does this potential race condition get resolved? This race condition is resolved by using synchronized keyword and locking provided by java. In order to call the wait (), notify () or notifyAll () methods in Java, we must have obtained the lock for the object on which we're calling the method. Since the wait () method in Java also releases the lock prior to waiting and reacquires the lock prior to returning from the wait () method, we must use this lock to ensure that checking the condition (buffer is full or not) and setting the condition (taking element from buffer) is atomic which can be achieved by using synchronized method or block in Java.

wait notify and notifyall in java synchronized
I am not sure if this is what interviewer was actually expecting but this what I thought would at least make sense, please correct me If I wrong and let us know if there is any other convincing reason of calling wait(), notify() or notifyAll method in Java.


Just to summarize we call wait (), notify () or notifyAll method in Java from synchronized method or synchronized block in Java to avoid:
1) IllegalMonitorStateException in Java which will occur if we don't call wait (), notify () or notifyAll () method from synchronized context.
2) Any potential race condition between wait and notify method in Java.


Some of my other favorite interview discussions are Why String is immutable or final in Java, how HashMap works in Java and what are differences between HashMap and hashtable in Java is.

22 comments :

Anand said...

Nice explanation Javin!!!

More details on Thread Communication can be found by Clicking Here

Anand

tangjie said...

Interesting.But I don't think so. When you use wait or notify or notifyAll,your code pattern always look:
if some condition is true then wait/notify
the condition check and the wait/notify must be atomic.Or some condition is true, but when you invoke notify/wait,the condition has changed.

By the way,if you need notification not lost, you may use semaphore.

Anonymous said...

Hi Javin, though I was familiar with IllegalMonitorStateException if not calling wait(), notify() or notifyAll() from synchronized method or block but the real and more convincing reason "race condition" was simply great.race condition in wait and notify

Anonymous said...

Another important thing you can mentioned about wait method in java is that "always call wait method inside a loop in java" because you need to test the condition before waiting and after waiting.

Anonymous said...

Can you also let us know Why do we need to call wait() method in Java in loop ? Also when should we use notify() and notifyAll() method in Java. I always confuse between notify() and notifyAll() so really looking forward to your answer.

thoughts_anshul said...

thanks ........ grt info

Anonymous said...

thanks!
clean and precise

Javin @ thread interview questions said...

Thanks for you comment Anonymous, Good to know that you find information on wait and notify useful.

Anonymous said...

Just to summarize we call wait (), notify () or notifyAll method in Java from synchronized method or synchronized block in Java to avoid:
1) IllegalMonitorStateException in Java which will occur if we don't call wait (), notify () or notifyAll () method from synchronized context.

Here are you saying that IllegalMonitorStateException will be thrown if you do NOT call wait/notify from a synchronized method??? Please clarify what exactly you mean here. - thanks

Javin @ why wait and notify defined in Object class said...

@Anonymous. you got it right. it means "if you don't use synchronized method or block for calling wait() and notify() method it will throw IllegalMonitorStateException"

Anonymous said...

All is fine, i am bit not comfortable with point #3 The Consumer thread calls the notify () method; this goes unheard since the Producer thread is not yet waiting.

how come this notification lost.

gopal krishna said...

hi boss nice explanation & i hv a question,

can we invoke a specific thread (t2) from object monitor state(assume 5 threads like t1,t2...t5)

nitus said...

Operating system uses a concept of "monitor" and "waitset" to handle multiple threads accessing a resource.In java this concept is implemented using "synchronized" and "'wait','notify' and 'notifyAll'".Here monitor refer to 'synchronized' and waitset includes all three methods.(as far as my knowledge is true)

Amol Pawar said...

wait method is called to release lock which thread has acquired and thread can acquire intrinsic lock only within synchronized block. If wait method has called outside synchronized block it does not know which lock should it release if it is not holding any lock. I am really skeptical about race condition being the reason for wait method to call inside synchronized block

Jawahar said...

I have been following up this blog for a long time and I am very much impressed with it. Lovely articles, Clear explanation and much more. Thank you for the wonderful blog.

Javin @ producer consumer solution BlockingQueue said...

@Achappn M, thanks for comment. Since buffer is full, producer can no longer add new items into buffer, hence producer thread should wait, until consumer, create space in buffer after consuming some items.

郭蕾 said...

I think this is a simple question,you should only answer : wait notify notifyAll is designed by thread communication.

satpan said...

We can not release a lock(using wait()) or notifying other threads to acquire lock with owning lock for any object. So before calling this function we need to own a lock using synchronized block or synchronized method.

Vandna Thakur said...

I super like your bloggings. Whenever i feel doubt regarding any topic i always go for your articles.

Here in this article i have one doubt that when "The Consumer thread calls the notify () method; this goes unheard since the Producer thread is not yet waiting." why Producer thread not go in wait state?
how come this notification lost?

Anonymous said...

Wont the compiler throw error when we try to call wait/notify from non-synchronized method?

Nitin Taur said...

Javin your argument is incorrect. Lets assume that inside Object class wait() and notify() method where synchronized. Now your producer/consumer solution need not to call these method from synchronized block. Will producer/consume work correctly? No because 'is buffer empty condition check and wait' must be atomic. Similarly, 'buffer is not empty check and notify' must be atomic operation.

The reason for this restriction is in implementation of wait/notify mechanism. Every object, in addition to having an associated monitor, has an associated wait set. A wait set is a set of threads.

When an object is first created, its wait set is empty. Elementary actions that add threads to and remove threads from wait sets are atomic. Wait sets are manipulated solely through the methods Object.wait, Object.notify, and Object.notifyAll. To protect wait set while calling wait/notify these methods must be called from within synchronized block/method. This method are not synchronized in Object class to enforce programmer to couple condition (buffer is full/empty) and call to these method as atomic operation.

bhs said...

I am not sure if your producer-consumer example is correct from the standpoint of race condition. What I mean is, producer uses push(Object x) function to put something in queue -- so this will be synchronized for all producer threads. Similarly a consumer will use the pop() method to empty the queue -- so this will be synchronized only for all consumer threads. If either of these methods are not synchronized a race condition should occur between the different producers OR different consumers. Not sure if the race condition will occur between producer AND consumer cos both are working on a different set of locks. Even if I synchronize push() or pop() methods... the behavior between producer threads or consumer threads should be undefined.

Let me know if my thinking is right. I think @Nitin's and @Satpan's explanation make more sense to me.

But anyways, you are a great guy. Your tutorials are really helpful...so keep up the great work of teaching java in simple english...

Post a Comment