I am learning multi-threading programming in Java, and the most difficult part seems to be inter-thread communication, using wait(), notify() and notifyAll().
I referred to official Javadoc of wait() , reproducing here:
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}
I got the point that when a thread t calls wait() it immediately releases the lock and then waits; however I am not able to understand what the condition in while loop means? Can't there be a chance before thread t checks for the condition in while loop the condition has been modified by some other thread?
Can anyone tell me what this condition is and what basic things are to be used in while loop for checking the condition?
You need not only to loop it but check your condition in the loop. Java does not guarantee that your thread will be woken up only by a notify()/notifyAll() call or the right notify()/notifyAll() call at all. Because of this property the loop-less version might work on your development environment and fail on the production environment unexpectedly.
For example, you are waiting for something:
synchronized (theObjectYouAreWaitingOn) {
while (!carryOn) {
theObjectYouAreWaitingOn.wait();
}
}
An evil thread comes along and:
theObjectYouAreWaitingOn.notifyAll();
If the evil thread does not/can not mess with the carryOn you just continue to wait for the proper client.
Edit: Added some more samples. The wait can be interrupted. It throws InterruptedException and you might need to wrap the wait in a try-catch. Depending on your business needs, you can exit or suppress the exception and continue waiting.
check below one also for your better clarity.
wait and notify are used to implement [condition variables](http://en.wikipedia.org/wiki/Monitor_(synchronization)#Blocking_condition_variables) and so you need to check whether the specific predicate you're waiting on is true before continuing.
The problem is the obj might call all waiting threads up by obj.notifyAll(), these woken up threads will enter syncronized code block in an uncertain order, and operate the shared data. So, it is necessary to check condition in while loop.
Suppose you have an empty queue, thread1 and thread2 is waiting to take element from it,
synchronized (obj) {
while (queue.isEmpty())
obj.wait();
... // Perform action appropriate to condition
queue.take();
}
After thread3 putting an element in this queue, and calls obj.notifyAll(), which will call thread1 and thread2 up:
thread1 wakes up first, find the only element in queue, and take it.
thread2 wakes up later, check if there is any element in queue by queue.isEmpty(), and wait()
again.
I am not able to understand what the condition in while loop means?
Literally, it means the logical inverse of the condition that you are waiting to happen.
Can't there be a chance before thread t checks for the condition in while loop the condition has been modified by some other thread?
The assumption1 is that the variables that make up the "condition" are only updated by another thread while it is holding the lock on obj.
Hence, at the point immediately after the while loop, the thread in the code above knows that the condition is now true, and nothing else will change it before it releases the lock.
Now ... obviously ... if some other thread is going to change the variables that make up the condition without holding the lock, then what you are worried about can happen. But that's a buggy program. You have shared variables being updated by different threads without adequate2 synchronization.
1 - The thread has to be holding that lock when it calls obj.notify() or obj.notifyAll(). (If not, you will get an exception.) But the guarded condition will also work if the variables are updated in a separate synchronized block to the notify call. It just makes the code harder to understand ...
2 - In this context, declaring variables as volatile is not sufficient for correct behavior of the guarded condition.
The condition in the head of a while loop can be any expression which resolves in a boolean.
In your example the while loop should suspend the execution of the real method until a certain condition is true.
Let's assume your synchronized method needs to be executed at 12pm and needs thread-safe access to the object obj
Then you head of the while loop would check if the current time is NOT 12pm. If this is true, the method cannot start it's real work. But to prevent blocking resources it will allow other threads to work with obj by calling obj.wait().
When we reach 12pm the condition of the while loop will be false and the thread exists the while loop and execute the rest of your code.
Related
I have read that we should always call a wait() from within a loop:
while (!condition) { obj.wait(); }
It works fine without a loop so why is that?
You need not only to loop it but check your condition in the loop. Java does not guarantee that your thread will be woken up only by a notify()/notifyAll() call or the right notify()/notifyAll() call at all. Because of this property the loop-less version might work on your development environment and fail on the production environment unexpectedly.
For example, you are waiting for something:
synchronized (theObjectYouAreWaitingOn) {
while (!carryOn) {
theObjectYouAreWaitingOn.wait();
}
}
An evil thread comes along and:
theObjectYouAreWaitingOn.notifyAll();
If the evil thread does not/can not mess with the carryOn you just continue to wait for the proper client.
Edit: Added some more samples.
The wait can be interrupted. It throws InterruptedException and you might need to wrap the wait in a try-catch. Depending on your business needs, you can exit or suppress the exception and continue waiting.
It's answered in documentation for Object.wait(long milis)
A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup. While this will rarely occur in practice, applications must guard against it by testing for the condition that should have caused the thread to be awakened, and continuing to wait if the condition is not satisfied. In other words, waits should always occur in loops, like this one:
synchronized (obj) {
while (<condition does not hold>)
obj.wait(timeout);
... // Perform action appropriate to condition
}
(For more information on this topic,
see Section 3.2.3 in Doug Lea's
"Concurrent Programming in Java
(Second Edition)" (Addison-Wesley,
2000), or Item 50 in Joshua Bloch's
"Effective Java Programming Language
Guide" (Addison-Wesley, 2001).
Why should wait() always be called inside a loop
The primary reason why while loops are so important is race conditions between threads. Certainly spurious wakeups are real and for certain architectures they are common, but race conditions are a much more likely reason for the while loop.
For example:
synchronized (queue) {
// this needs to be while
while (queue.isEmpty()) {
queue.wait();
}
queue.remove();
}
With the above code, there may be 2 consumer threads. When the producer locks the queue to add to it, consumer #1 may be blocked at the synchronized lock while consumer #2 is waiting on the queue. When the item is added to the queue and notify called by the producer, #2 is moved from the wait queue to be blocked on the queue lock, but it will be behind the #1 consumer which was already blocked on the lock. This means that the #1 consumer gets to go forward first to call remove() from the queue. If the while loop is just an if, then when consumer #2 gets the lock after #1 and calls remove(), an exception would occur because the queue is now empty -- the other consumer thread already removed the item. Even though it was notified, it needs to be make sure the queue is for sure not empty because of this race condition.
This well documented. Here's a web page I created a while back which explains the race condition in detail and has some sample code.
There might be more then just one worker waiting for a condition to become true.
If two or more worker get awake (notifyAll) they have to check the condition again.
otherwise all workers would continue even though there might only be data for one of them.
I think I got #Gray 's answer.
Let me try to rephrase that for newbies like me and request the experts to correct me if I am wrong.
Consumer synchronized block::
synchronized (queue) {
// this needs to be while
while (queue.isEmpty()) {
queue.wait();
}
queue.remove();
}
Producer synchronized block::
synchronized(queue) {
// producer produces inside the queue
queue.notify();
}
Assume the following happens in the given order:
1) consumer#2 gets inside the consumer synchronized block and is waiting since queue is empty.
2) Now, producer obtains the lock on queueand inserts inside the queue and calls notify().
Now,either consumer#1 can be chosen to run which is waiting for queue lock to enter the synchronized block for the first time
or
consumer#2 can be chosen to run.
3) say, consumer#1 is chosen to continue with the execution. When it checks the condition,it will be true and it will remove() from the queue.
4) say,consumer#2 is proceeding from where it halted its execution (the line after the wait() method). If 'while' condition is not there (instead an if condition), it will just proceed to call remove() which might result in an exception/unexpected behaviour.
Because wait and notify are used to implement [condition variables](http://en.wikipedia.org/wiki/Monitor_(synchronization)#Blocking_condition_variables) and so you need to check whether the specific predicate you're waiting on is true before continuing.
Both safety and liveness are concerns when using the wait/notify mechanism. The safety property requires that all objects maintain consistent states in a multithreaded environment. The liveness property requires that every operation or method invocation execute to completion without interruption.
To guarantee liveness, programs must test the while loop condition before invoking the wait() method. This early test checks whether another thread has already satisfied the condition predicate and sent a notification. Invoking the wait() method after the notification has been sent results in indefinite blocking.
To guarantee safety, programs must test the while loop condition after returning from the wait() method. Although wait() is intended to block indefinitely until a notification is received, it still must be encased within a loop to prevent the following vulnerabilities:
Thread in the middle: A third thread can acquire the lock on the shared object during the interval between a notification being sent and the receiving thread resuming execution. This third thread can change the state of the object, leaving it inconsistent. This is a time-of-check, time-of-use (TOCTOU) race condition.
Malicious notification: A random or malicious notification can be received when the condition predicate is false. Such a notification would cancel the wait() method.
Misdelivered notification: The order in which threads execute after receipt of a notifyAll() signal is unspecified. Consequently, an unrelated thread could start executing and discover that its condition predicate is satisfied. Consequently, it could resume execution despite being required to remain dormant.
Spurious wakeups: Certain Java Virtual Machine (JVM) implementations are vulnerable to spurious wakeups that result in waiting threads waking up even without a notification.
For these reasons, programs must check the condition predicate after the wait() method returns. A while loop is the best choice for checking the condition predicate both before and after invoking wait().
Similarly, the await() method of the Condition interface also must be invoked inside a loop. According to the Java API, Interface Condition
When waiting upon a Condition, a "spurious wakeup" is permitted to
occur, in general, as a concession to the underlying platform
semantics. This has little practical impact on most application
programs as a Condition should always be waited upon in a loop,
testing the state predicate that is being waited for. An
implementation is free to remove the possibility of spurious wakeups
but it is recommended that applications programmers always assume that
they can occur and so always wait in a loop.
New code should use the java.util.concurrent.locks concurrency utilities in place of the wait/notify mechanism. However, legacy code that complies with the other requirements of this rule is permitted to depend on the wait/notify mechanism.
Noncompliant Code Example
This noncompliant code example invokes the wait() method inside a traditional if block and fails to check the postcondition after the notification is received. If the notification were accidental or malicious, the thread could wake up prematurely.
synchronized (object) {
if (<condition does not hold>) {
object.wait();
}
// Proceed when condition holds
}
Compliant Solution
This compliant solution calls the wait() method from within a while loop to check the condition both before and after the call to wait():
synchronized (object) {
while (<condition does not hold>) {
object.wait();
}
// Proceed when condition holds
}
Invocations of the java.util.concurrent.locks.Condition.await() method also must be enclosed in a similar loop.
Before getting to the answer, lets see how wait is probably implemented.
wait(mutex) {
// automatically release mutex
// and go on wait queue
// ... wait ... wait ... wait ...
// remove from queue
// re-acquire mutex
// exit the wait operation
}
In your example mutex is the obj with the assumption that your code is running inside synchronized(obj) { } block.
A mutex is called as monitor in Java [some subtle differences though]
A concurrency example using condition variable with if
synchronized(obj) {
if (!condition) {
obj.wait();
}
// Do some stuff related to condition
condition = false;
}
Lets say we have 2 threads. Thread 1 and Thread 2.
Lets see some states along the timeline.
at t = x
Thread 1 state:
waiting on ... wait ... wait ... wait ..
Thread 2 state:
Just entered the synchronised section, since as per the thread 1's state, the mutex/monitor is released.
You can read more about wait() here java.sun.com/javase/6/docs/api/java/lang/Object.html#wait(long).
This is the only thing that is tricky to understand. When 1 thread is inside the synchronized block. Another thread can still enter the synchronized block because wait() causes the monitor/mutex to be released.
Thread 2 is about to read if (!condition) statement.
at t = x + 1
notify() is triggered by some thread on this mutex/monitor.
condition becomes true
Thread 1 state:
Waiting at re-acquire mutex, [Since thread-2 has the lock now]
Thread 2 state:
Doesn't go inside if condition and marks the condition = false.
at t = x + 2
Thread 1 state:
Exits the wait operation and about to mark condition = false.
This state is inconsistent as condition is supposed to be true but is false already, because thread 2 marked it false previously.
And thats the reason, while is required instead of if. As while would trigger the condition to be checked again for thread 1 and thread 1 will begin waiting again.
Result
In order to avoid this inconsistency the correct code seems to be like this:
synchronized(obj) {
while (!condition) {
obj.wait();
}
// Do some stuff related to condition
condition = false;
}
From your Question:
I have read that we should always called a wait() from within a loop:
Although wait( ) normally waits until notify( ) or notifyAll( ) is called, there is a possibility that in very rare cases the waiting thread could be awakened due to a spurious wakeup. In this case, a waiting thread resumes without notify( ) or notifyAll( ) having been called.
In essence, the thread resumes for no apparent reason.
Because of this remote possibility, Oracle recommends that calls to wait( ) should take place within a loop that checks the condition on which the thread is waiting.
Three things you will see people do:
Using wait without checking anything (BROKEN)
Using wait with a condition, using an if check first (BROKEN).
Using wait in a loop, where the loop test checks the condition (NOT BROKEN).
Not appreciating these details about how wait and notify work leads people to choose the wrong approach:
One is that a thread doesn't remember notifications that happened before it got around to waiting. The notify and notifyAll methods only effect threads that are already waiting, if a thread isn't waiting at the time it is out of luck.
Another is that a thread releases the lock once it starts waiting. Once it gets a notification it re-acquires the lock and continues on where it left off. Releasing the lock means that thread does not know anything about the current state once it wakes back up, any number of other threads could have made changes since then. The check made before the thread started waiting doesn't tell you anything about what the state is currently.
So the first case, with no checking, makes your code vulnerable to race conditions. It might happen to work by accident if one thread has enough of a head start over another. Or you may have threads waiting forever. If you sprinkle in timeouts then you end up with slow code that sometimes doesn't do what you want.
Adding a condition to check apart from the notification itself protects your code from these race conditions and gives your code a way to know what the state is even if the thread wasn't waiting at the right time.
The second case, with if-checks, is likely to work if you have only 2 threads. That puts a limit on the number of states things can get into and when you made faulty assumptions you don't get burned so badly. This is the situation for lots of toy example code exercises. The result is people come away thinking they understand, when they really don't.
Protip: Real world code has more than two threads.
Using the loop lets you re-check the condition once you re-acquire the lock so that you're moving forward based on current state, not on stale state.
In simple words,
'if' is a conditional statement , once condition is satisfied remaining block of code will get executed.
'while' is a loop which going check the condition unless condition is not satisfied.
I am in doubt with that , in Java language, we need to acquire the lock, before we await some condition to be satisfied.
For example, int java monitor lock:
synchronized(lock){
System.out.println("before lock ...");
lock.wait();
System.out.println("after lock ...");
}
or the concurrency utils:
Lock lock = new ReentrantLock();
Condition cond = lock.newCondition();
lock.lock();
try{
System.out.println("before condition ...");
cond.await();
System.out.println("after condition ...");
}catch(Exception e){
e.printStackTrace();
}finally{
lock.unlock();
}
So, why we can't await, without hold the lock ?
Does other languages differ, or it's just in Java?
I hope you can explain the reason after the design, but not only for JAVA-SPEC definition.
Imagine you have something that a thread might need to wait for. Maybe you have a queue and a thread needs to wait until there's something on the queue so it can process it. The queue must be thread-safe, so it has to be protected by a lock. You might write the following code:
Acquire the lock.
Check if the queue is empty.
If the queue is empty, wait for the something to be placed on the queue.
Oops, that won't work. We hold the lock on the queue so how can another thread place something on it? Let's try again:
Acquire the lock.
Check if the queue is empty.
If the queue is empty, release the lock and wait for the something to be placed on the queue.
Oops, now we still have a problem. What if after we release the lock but before we wait for something to be placed on the queue, something is placed on the queue? In that case, we will be waiting for something that already happened.
Condition variables exist to solve this exact problem. They have an atomic "unlock and wait" operation that closes this window.
So await must hold the lock because otherwise there would be no way to ensure you weren't waiting for something that already happened. You must hold the lock to prevent another thread from racing with your wait.
Well, what are we waiting for? We are waiting for a condition to become true. Another thread will make the condition true, then notify the waiting threads.
Before entering wait, we must check that the condition is false; this check and the wait must be atomic, i.e. under the same lock. Otherwise, if we enter the wait while the condition is already true, we'll likely never wakeup.
Therefore it is necessary that the lock is already acquired before calling wait()
synchronized(lock)
{
if(!condition)
lock.wait();
If wait() automatically and silently acquires lock, a lot of bugs will go undetected.
Upon wakeup from wait(), we must check the condition again -- there's no guarantee that the condition must become true here (for lots of reasons - spurious wakeup; timeout, interruption, multiple waiters, multiple conditions)
synchronized(lock)
{
if(!condition)
lock.wait();
if(!condition) // check again
...
Typically, if the condition is still false, we'll wait again. Therefore the typical pattern is
while(!condition)
lock.wait();
But there are also cases where we don't want to wait again.
Could there ever be legit use cases where naked wait/notify make sense?
synchronized(lock){ lock.wait(); }
Sure; an application can be made up with naked wait/notify, with well defined behavior; argument can be made that this is the desired behavior; and this is the best implementation for that behavior.
However, that is not the typical usage pattern, and there is no reason to account for it in API design.
See the doc for Condition.
A Condition is like a wait pool or wait set of an object and it replaces the use of the Object monitor methods (wait, notify and notifyAll). Conditions enable one thread to suspend execution (to "wait") until notified by another thread that some state condition may now be true. A Condition instance is intrinsically bound to a lock just like the Object monitor methods require the lock of the shared object to wait or notify on. So before invoking await() on a condition, the thread must have locked the Lock object that is used to produce the condition. When the await() method is invoked, the lock associated with the condition is released.
If the thread were merely waiting for a signal to proceed there are other mechanisms for doing that. Presumably there is some state protected by the lock that the thread is waiting to be operated on and satisfy some condition. To properly protect that state the thread should have the lock before and after waiting for the condition, so it makes sense to require acquisition of the lock.
a sounds-reasonable answer
It is a JVM thing. An Object x has:
an Entry Set: a queue for threads attempting to synchronized(x)
a Waiting Set: a queue for threads called x.wait()
When you call x.wait(), JVM adds your current thread into Waiting Set; when you call x.notify()/x.notifyAll(), JVM removes one/all element from Waiting Set.
Multiple threads may call x.wait()/x.notify()/x.notifyAll() to modify the Waiting Set. In order to ensure the Waiting Set thread safety, JVM accepts only one operation from one thread at one time.
Simple answer is because otherwise you will get IllegalMonitorStateException which is specified in Object.wait javadoc. Internally, synchronization in Java uses underlying OS mechanizm. So it is not only Java.
Unfortunately I'm not going to be able to give full context to this, since there's too much complexity in the surrounding code. The short of it is this:
I have a block of code that's waiting on a lock:
synchronized (lock) {
lock.wait();
}
Which works as expected. Fairly straightforward -- it acquires the lock, releases it when it starts waiting, another thread acquires the lock and then notifies on it.
However, as soon as I provide a timeout, the behavior changes entirely.
synchronized (lock) {
lock.wait(60000L);
}
Again, should be fairly straightforward (and this works as expected in several other places in the code). However, in this one case, execution basically halts until the timeout occurs. My only guess as to what seems to be happening is it's not releasing the lock when it enters the wait -- the notifier is never able to acquire the lock, so the wait sleeps until it times out. And even worse, it's a blocking sleep -- no other threads are able to wait on the lock and it forces the execution to be entirely synchronous.
Anyone have any ideas as to what might be happening here? It's a fairly simple function and there's nothing weird going on with nested synchronization blocks at any point. Considering that by providing no timeout it should wait indefinitely, if the notifier itself was broken the code would be hanging forever, but that's not the case. It only stops working once the timeout is provided.
Any thoughts would be greatly appreciated.
OS: OS X 10.8.5
JDK: 1.6.0, 1.7.0.45 and 1.7.0.67
Your example does not show a while() loop around the wait() call. That suggests that you may not completely understand the use case for wait and notify. Here's one example:
// This object is used to synchronize *EVERY* method
// that can change the value of count.
final Object lock = new Object();
int count;
void waiter() {
synchronized(lock) {
while(count <= 0) {
lock.wait();
}
//do something that you are only allowed to do
//when count > 0.
}
}
void notifier() {
synchronized(lock) {
count++;
if (count >= 0) {
lock.notify();
}
}
}
[Edit: Added this paragraph, thank's Nathan Hughes for reminding me that...] The wait() call is in a loop because the wait()ing thread still has to re-acquire the lock after the lock has been notified: if thread A is waiting for the condition to become true, and thread B makes the condition true and calls notify(); there's no guarantee that thread C won't get the lock first, and make the condition false again before the wait() call is able to return.
Also, wait() is allowed to return even when the object has not been notified (that's called a "spurious wakeup").
The condition-to-be-waited-for is explicit in the code (i.e., count > 0).
Nothing changes the condition-to-be-waited-for except when synchronized on the same lock object that is used for wait() and notify() calls.
Irrespective of whether you provide a timeout or not the wait method on an object releases the lock held on the object by the current thread as commented by John.
With the code that you have given and based on your description of scenario my guess is that the moment lock.wait(60000L) is executed JVM releases the lock on the object meanwhile any other thread which is in runnable/running state might be picked up and if they are synchronizing on the same object then they might take the lock before your notifier thread would take the lock.
This behaviour is difficult to debug as it depends on JVM profiler to pick which thread should be run. So as you explained just when your lock.wait(60000L) is executed it need not always be that the notifier thread alone should pick up the lock on the common object . If there is any other thread which is also waiting on the common object it can very well get the lock finally leading to notifier thread not being able to get the lock and hence the lock.wait(60000L) gets timedout.
Whenever you use lock.wait(..) you have to use the lock.notify() or lock.notifyAll(). Make sure you use that where it makes sense in your logic and it will 'wake up' the lock before the timeout (considering the timeout value you put is enough). Here it's some guide for its usage, i hope its useful: http://www.javamex.com/tutorials/wait_notify_how_to.shtml
I am trying to figure out a solution to the following problem:
public void signal(){
//resets condition and signals threads blocked below
}
public void getValue(){
waitOnCondition(); //block if a condition is not met. When signalled, all threads should proceed and get the value
//get value
resetCondition(); //reset condition, so that the next thread that executes this method blocks on the method above
}
The issue I am facing seems to be simple, but I am struggling to see how all the edge cases can be captured.
One solution might be to use Locks with Conditions, then all threads witing on waitOnCondition are going to await until a flag is set to true and then proceed, for example. The thread executing signal() would then use the same lock, set the flag to true and signal. Then, the released threads would reacquire the lock to set the condition to false. This, however, does not guarantee that all the threads are going to reach the getValue point. For instance:
Thread 1 and 2 are waiting, get the signal. After being signalled, thread 1 reacquires the lock, checks the condition, now true, and proceeds. gets the value, acquires the lock and sets condition to false. Thread 2, now sees the condition still as false, and blocks again.
Another solution, quite neat and elegant, would be to use a CountDownLatch. This guarantees that all the threads are going to proceed. This is, however, not resettable. Any other ideas or comments?
Seems like CyclicBarrier is what you need. It is resettable and also allows to trigger a barrier action when all parties are there.
There is also Phaser which is an advanced version of CyclicBarrier and it requires JDK 7 to run.
Someone at work just asked for the reasoning behind having to wrap a wait inside a synchronized.
Honestly I can't see the reasoning. I understand what the javadocs say--that the thread needs to be the owner of the object's monitor, but why? What problems does it prevent? (And if it's actually necessary, why can't the wait method get the monitor itself?)
I'm looking for a fairly in-depth why or maybe a reference to an article. I couldn't find one in a quick google.
Oh, also, how does thread.sleep compare?
edit: Great set of answers--I really wish I could select more than one because they all helped me understand what was going on.
Lots of good answers here already. But just want to mention here that the other MUST DO when using wait() is to do it in a loop dependent on the condition you are waiting for in case you are seeing spurious wakeups, which in my experience do happen.
To wait for some other thread to change a condition to true and notify:
synchronized(o) {
while(! checkCondition()) {
o.wait();
}
}
Of course, these days, I'd recommend just using the new Condition object as it is clearer and has more features (like allowing multiple conditions per lock, being able to check wait queue length, more flexible schedule/interrupt, etc).
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
lock.lock();
try {
while (! checkCondition()) {
condition.await();
}
} finally {
lock.unlock();
}
}
If the object does not own the object monitor when it calls Object.wait(), it will not be able to access the object to setup a notify listener until the the monitor is released. Instead, it will be treated as a thread attempting to access a method on a synchronized object.
Or to put it another way, there is no difference between:
public void doStuffOnThisObject()
and the following method:
public void wait()
Both methods will be blocked until the object monitor is released. This is a feature in Java to prevent the state of an object from being updated by more than one thread. It simply has unintended consequences on the wait() method.
Presumably, the wait() method is not synchronized because that could create situations where the Thread has multiple locks on the object. (See Java Language Specifications/Locking for more info on this.) Multiple locks are a problem because the wait() method will only undo one lock. If the method were synchronized, it would guarantee that only the method's lock would be undone while still leaving a potential outer lock undone. This would create a deadlock condition in the code.
To answer your question on Thread.sleep(), Thread.sleep() does not guarantee that whatever condition you are waiting on has been met. Using Object.wait() and Object.notify() allows a programmer to manually implement blocking. The threads will unblock once a notify is sent that a condition has been met. e.g. A read from disk has finished and data can be processed by the thread. Thread.sleep() would require the programmer to poll if the condition has been met, then fall back to sleep if it has not.
It needs to own the monitor, since the purpose of the wait() is to release the monitor and let other threads obtain the monitor to do processing of their own. The purpose of these methods (wait/notify) is to coordinate access to synchronized code blocks between two threads that require each other to perform some functionality. It is not simply a matter of making sure access to a data structure is threadsafe, but to coordinate events between multiple threads.
A classic example would be a producer/consumer case where one thread pushes data to a queue, and another thread consumes the data. The consuming thread would always require the monitor to access the queue, but would release the monitor once the queue is empty. The producer thread would then only get access to write to the thread when the consumer is no longer processing. It would notify the consumer thread once it has pushed more data into the queue, so it can regain the monitor and access the queue again.
Wait gives up the monitor, so you must have it to give it up. Notify must have the monitor as well.
The main reason why you want to do this is to ensure that you have the monitor when you come back from wait() -- typically, you are using the wait/notify protocol to protect some shared resource and you want it to be safe to touch it when wait returns. The same with notify -- usually you are changing something and then calling notify() -- you want to have the monitor, make changes, and call notify().
If you made a function like this:
public void synchWait() {
syncronized { wait(); }
}
You would not have the monitor when wait returned -- you could get it, but you might not get it next.
Here's my understanding on why the restriction is actually a requirement. I'm basing this on a C++ monitor implementation I made a while back by combining a mutex and a condition variable.
In a mutex+condition_variable=monitor system, the wait call sets the condition variable into a wait state and releases the mutex. The condition variable is shared state, so it needs to be locked to avoid race conditions between threads that want to wait and threads that want to notify. Instead of introducing yet another mutex to lock its state, the existing mutex is used. In Java, the mutex is correctly locked when the about-to-wait thread owns the monitor.
Mostly wait is done if there is a condition say a queue is empty.
If(queue is empty)
queue.wait();
Let us assume the queue is empty.
In case if the current thread pre-empts after checking the queue, then if another
thread adds few elements to queue, the current thread will not know and will go for wait
state. Thats wrong.
So we should have something like
Synchornized(queue)
{
if(queue is empty)
queue.wait();
}
Now let us consider what if they made wait itself as synchronized. As already mentioned in one of the comments, it releases only one lock. That means if wait() was synchronized in the above code only one lock would have been released. Implies that current thread will go for wait with the lock for the queue.