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.

Please share with your friends if like this article

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.

Sutanu said...

I think Amol Pawar's reply makes more sense.

Achappan M said...

I am also one of ur fan for your articles. Thanks for such a wonderful bloggings. Here I have one doubt in this article what you are meaning about buffer where producer is waiting after buffer is full.

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.

Anonymous said...

Great Work man

Pratap Chandra Mohanty said...

Very good articles posted on this blog..really great help for core concepts

郭蕾 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.

Post a Comment