This week's book giveaway is in the Servlets forum.
We're giving away four copies of Murach's Java Servlets and JSP and have Joel Murach on-line!
See this thread for details.
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Thread question Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Thread question" Watch "Thread question" New topic
Author

Thread question

Ramesh Tiwari
Greenhorn

Joined: Jul 03, 2003
Posts: 9
Why do we need to call wait() and notify in a synchronized context,in other words, why do we need to get the lock of the object to call wait().
Why can't we directly call wait() on an object without locking the object.
Please explain.
Thanks
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
I hope you don�t mind a long answer. But the question you have asked is very important and should be treated accordingly.
Why do we need to call wait() and notify in a synchronized context

A thread might not want to perform some action on an object unless it is guaranteed that object is in the correct state.
There are two approaches to handle this. (1) Optimistic try-and-see: Methods can always be tried when invoked, but do not always succeed, and thus may have to deal with failure. (2) Conservative check and act: Methods refuse to proceed unless preconditions hold. When preconditions do hold, the actions always succeed.
The wait-and-notify mechanism uses the conservative approach. The thread blocks until a precondition becomes true.
The standard coding idiom (which we rarely if ever see in these exam prep books and mock exams) is a simple while loop invoking wait.

Everything is executed in synchronized code. If it were not, the state of the object would not be stable. If the method were not declared synchronized, then after the while statement, there would be no guarantee that the condition remained true because another thread may have changed the condition that is being tested.
On the other side, the notification methods are invoked by synchronized code that changes one or more conditions on which some other thread may be waiting.
[ July 13, 2003: Message edited by: Marlene Miller ]
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
I am still working on understanding the concepts underlying the wait-notify mechanism.
A better answer to your question has something to do with monitors. Entities possessing both locks and wait sets are generally called monitors. In Java, any Object can serve as a monitor.
A monitor provides a set of operations that are the only means by which an object can be manipulated. A process can access the variables in a monitor only by calling one of the monitor�s procedures.
Monitor procedures by definition execute with mutual exclusion. In particular, it is up the implementation of the language, library, or operating system to provide mutual exclusion. It is not up to the programmer who uses monitors. In practice, languages and libraries implement mutual exclusion by using locks or semaphores.
Gregory Andrews, Foundations of Multithreaded, Parallel, and Distributed Programming
See Chapter 5: Monitors and Case Study: Java
[ July 13, 2003: Message edited by: Marlene Miller ]
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
Three more thoughts on this question:
(1) I gave two relatively elaborate answers above, one about guarded methods (according to Doug Lea) and the other about monitors (according to Gregory Andrews).
But Paul Hyde has a nice simple way of explaining it in his book Java Thread Programming. He says the checking and modification occur inside the synchronized blocks to be sure that no race conditions develop. Synchronization on the object controls concurrent access to the object.
(2) Paul Hyde also points out that the wait/notify mechanism does not *require* that a condition be checked by one thread and set by another. However, it is generally a good idea to use this mechanism in conjunction with at least one variable. Doing so helps in avoiding missed notifications and in detecting early notifications. He gives two very nicely written examples.
(3) In truth, I could not explain above why notify must be synchronized. After all, when the second thread notifies the waiting thread(s) and then exits the synchronized block, another thread could change the condition again before the notified thread(s) is scheduled to run again.
Now I know why. The waiting thread of course has to be synchronized, so that the state of the object does not change between the time the condition is checked and the code after the condition executes. Therefore, all methods reading or changing the condition must be synchronized. Otherwise the first thread might test the condition, then the second thread in an unsynchronized method changes the condition and calls notify that is ignored, then the first thread calls wait and misses the notification.
(As you can see, this question really interests me. For a long while I use to wonder the same thing myself. Sorry for the long posts. The better I understand it, the more concise my answers will become.)
Ramesh Tiwari
Greenhorn

Joined: Jul 03, 2003
Posts: 9
Thank you very much Marlene.
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
Ramesh, I hope you were able to condense what I said into something meaningful and useful to you. I hope you did not suffer from buffer overflow.
It's the first time I have tried to articulate these interesting ideas on wait-and-notify. I got a bit carried away, didn't I?
I am sure I will hear about it from some of the other Ranch hands.
Anupam Sinha
Ranch Hand

Joined: Apr 13, 2003
Posts: 1088
Hi Marlene
I agree with you this question is really interesting. Sometime back I thought about this thing and then after getting no concrete answer just left the question.

(3) In truth, I could not explain above why notify must be synchronized. After all, when the second thread notifies the waiting thread(s) and then exits the synchronized block, another thread could change the condition again before the notified thread(s) is scheduled to run again.
Now I know why. The waiting thread of course has to be synchronized, so that the state of the object does not change between the time the condition is checked and the code after the condition executes. Therefore, all methods reading or changing the condition must be synchronized. Otherwise the first thread might test the condition, then the second thread in an unsynchronized method changes the condition and calls notify that is ignored, then the first thread calls wait and misses the notification.

I still don't understand why notify must be synchronized. As you just said it is very much possibe that the first thread calls notify and the second thread that should now execute doesn't executes and instead a third thread executes and causes the data to be changed which is to be used by the second thread.

Otherwise the first thread might test the condition, then the second thread in an unsynchronized method changes the condition and calls notify that is ignored, then the first thread calls wait and misses the notification.

Here is the first thread synchronized? If yes then the second thread can not change the condition if the lock is obtained on the condition(which should be done) unless wait is called(or somehow the lock is released). Now when wait() has been called then the second unsynchronized thread's notify should be acknowledged.
In case the first thread is not synchronized then the condition can change anytime during the course of the execution of the program.
I am attaching an application that does the following :
1. Producer produces the output. Producer is synchronized.
2. Consumer should consume the output. Consumer is synchronized.
3. Sometimes the hijacker steps in and changes the output. Hijacker is not synchronized.
What should happen is producer should produce and then issue a wait. Then consumer should consume and then it should also issuse a wait and notify the producer. But sometimes what happens is hijacker thread comes in between and changes the output to something else. This happens when producer has produced and is waiting for consumer for consume.
But I don't understand why hijacker though having a priority of 10 only comes into play a very limited no. of times. So you may have to run this application a few times before actually getting to the desired output.
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
Hi Anupam. I am getting NullPointerExceptions when I add print statements to class hijack.
Exception in thread "main" java.lang.NullPointerException
at java.lang.Thread.setPriority(Thread.java:882)
at ThreadCheck.main(Test59.java:18)
Then I removed code that does not affect the exception. Do you also get a NullPointerException?

hijack run()
java.lang.NullPointerException
at hijack.run(Test59.java:26)
at java.lang.Thread.run(Thread.java:536)
Anupam Sinha
Ranch Hand

Joined: Apr 13, 2003
Posts: 1088
Had to modify the output because probably : and P were being considered as a smiley( ) and no more than 8 are allowed.
Outputs that I got :

This output is not from start

There were other outputs as well. But were mainly variations of the above outputs.
I only got the java.lang.NullPointerException only twice. I ran the program 20 times or so. Try this put t_hijack.setPriority(10); before t_hijack.start();.
As follows
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
Ramesh, how would you like a really nice and short answer to your question? I found this in Doug Lea's Concurrent Programming in Java:
"Because of the way in which wait sets interact with locks, the methods wait, notify, and notifyAll may be invoked only when the synchronized lock is held on their targets."
(Well... what exactly does he mean by "the way"?)
[ July 17, 2003: Message edited by: Marlene Miller ]
 
It is sorta covered in the JavaRanch Style Guide.
 
subject: Thread question
 
Similar Threads
sending images...
serialization
A question on wait().
Why do we need object oriented databases
Need for init() method