Why do we need notify() for inter thread communication - java

From the JAVA docs for Object notify()
The awakened thread will not be able to proceed until the current
thread relinquishes the lock on this object.
This means that unless the Thread which notifes, its synchronized block is complete and it releases the lock, the waiting thread cannot proceed. If that's the case then whats the point of having notify() if the sync block is going to be executed anyway? What's the actual use of notify() if it doesn't wake up the waiting thread and let it do its job?

Good question. Will point you to take a look at the Thread State Class.
A thread that calls the Object.notify method enables a thread that previously called Object.wait is now enabled to be scheduled by the thread scheduler. In parlance, the thread that was waiting is now "runnable". Although it is "runnable", it is not "running".
It can only continue running when the thread invoking notify releases the lock - one way is when it exits out of the synchronized block.
There are a lot of schematics on the web on the Thread States. Some of them are completely incorrect or confusing since they introduce terminology not in the official docs. Here is one that makes sense to me.

Strictly speaking, we don't: we could have the waiting thread run a loop where it re-acquires the lock, checks the condition, and sleeps for a short amount of time. But using wait() and notify() is much more efficient, because then the waiting thread doesn't keep waking up and tying up CPU (and tying up the lock).

notify() and notifyAll() are used to wake up thread(s) that called wait() on the same object on which notify() or notifyAll() is called.
Without call to notify() those "waiting" threads will wait forever (although JVM spec says that threads may sometime wake up without call to notify).
Also because call to notify() doesn't releases the lock associated with the object itself that call usually is the last statement in a synchronized block.
So notify() is used together with wait() and not by itself.
Usually the use case is like the following (blocking queue with limited size).
Method that adds element to queue (some pseudo code)
synchronized(lockObject) {
if (size < LIMIT) {
addElement();
lockObject.notifyAll(); //notifying threads that are waiting to get element from empty queue
} else {
lockObject.wait(); // waiting for other thread to get element from queue and make room for new element
}
}
Method that gets element
synchronized(lockObject) {
if (size > 0) {
getElement();
lockObject.notifyAll(); // notify threads that there is a room for new element
} else {
lockObject.wait(); // waiting for other thread to put element into the queue
}
}
Also calling lockObject.wait() releases lock on lockObject. More details regarding that could be found here: Java : Does wait() release lock from synchronized block

Notifying is what wakes up a thread that is waiting. If you remove the notify then waiting threads stay waiting (barring spurious wakeups but let’s not go there for now).
(Interrupting wakes up the thread but the guidance is to use it for cancellation only. Interruption targets a specific thread, where notifying lets the scheduler decide which threads are affected.)
When a thread calls wait it has to have the lock, then the wait method lets go of the lock.
When a thread calls notify it has to have the lock.
As a practical matter the notify can’t take effect on any waiting thread until the notifying thread relinquishes the lock. The first thing the notified thread is going to need to do anyway is to try to acquire the lock. All the passage you're quoting is trying to say is that the wakeup doesn't occur instantaneously when a thread calls notify.
So what happens here is that the notifying thread lets go of the lock and sends the notify to the scheduler, the scheduler decides which thread to notify, then the notified thread wakes up and contends for the lock in order to leave the wait method.

Imagine if you need a thread to wait for another thread to do something that it may or may not even currently be actively working on. For example, a thread that's waiting for a job to do may need to wait until another thread has put a job on the list of jobs it should do if that list is empty. How would you do this?
You can't just use some form of mutual exclusion. There may be long periods of time when there's no work to do and not thread holds any lock on the queue. There may just not be any work to do right now. The thread that does work needs to wait, without holding any lock, until another thread has given it some work to do.
So somewhere, there's a thread that does something like this:
Acquire the lock that protects some shared state that another thread might be waiting for a change to. (In this case, the job queue.)
Change the shared state to reflect the fact that the thing a thread might need to wait for has happened. (That is, put a job on the queue.)
Release the lock and let any waiting thread(s) know that the thing has happened.
So what could our code to wait look like? Perhaps:
Acquire the lock that protects the shared state.
Check whether we need to wait or not. (Is there a job on the queue?)
If we need to wait, wait. (If not, wait for a job to be placed on the queue.)
...
Oops, we have a problem. The thing we're waiting for can't happen because we hold the lock. No other thread can change the shared state. (Our thread to put a job on the queue can't touch the queue until we release the lock we acquired in step 1.)
Let's try it again:
Acquire the lock that protects the shared state.
Check whether we need to wait or not. (Is there a job on the queue?)
If we don't need to wait, exit this algorithm. (If there's a job, take it off the queue, release the lock, and do it.)
Release the lock. (So another thread can put a job on the queue.)
Wait for the thing to happen.
...
Oops, we have another problem. What if the thing we're waiting for happens after step 4 but before step 5. Since the lock has been released, the thing we're waiting for can happen. We can't check again because we don't hold the lock. How can we ensure we don't wait for something that has already happened, which may mean waiting forever?
To solve this, we need an atomic "unlock and wait" operation. That's what wait does. And we also need some operation that can end this wait that can be called by the thread that changed the shared state so that we no longer need to wait. That's what notify does.

Related

What is happening when calling wait() method

I read in a Java textbook the following pertaining to multi-threading.
For a thread to call wait() or notify(), the thread has to be the owner of the lock for that object. When
the thread waits, it temporarily releases the lock for other threads to use, but it will need
it again to continue execution.
I'm confused about what is meant by the clause
When the thread waits, it temporarily releases the lock for other
threads to use
I don't get what that clause is talking about. Is it saying that when the wait() method is called it is actually releasing the lock before the wait() returns (i.e. this happens without caller knowing)? Or is it just alluding to wait(timeout) releasing the lock when the timeout elapses? If it is the former why would it release the lock before notify()? This seems like a vague and poorly explained statement.
For a thread to call wait() or notify(), the thread has to be the owner of the lock for that object.
Otherwise, a runtime error occur and the rest of code is not executed.
When the thread waits, it temporarily releases the lock for other threads to use
In more details, call to wait() does the following:
the lock is released
current thread is registered as waiting in the monitor
processor switches to some other thread ready for execution
Then, some thread calls notify() or notifyAll(), which causes one or all threads which are registered as waiting at this monitor to be moved from the wait set to the ready set, waiting for a free processor to execute.
but it will need it again to continue execution.
This means the execution of the thread is continued with executing synchronized statement to regain the lock. After the lock is aquired, then the wait() method returns. wait(timeout) differs in that except for notify() or notifyAll(), it also can return upon the timeout.
In sum, you need to understand how a thread switches between following 4 states:
running on a processor
blocked on synchronized statement
waiting for notification
ready to execute and waiting for a free processor
When a thread calls wait, the thread releases the lock right away and then goes dormant until either the timeout expires, if any, or until it receives a notification, which occurs when another thread acquires the same lock that the waiting thread gave up and calls notify on it (also the scheduler has to pick the waiting thread from among any other waiting threads; calling notify doesn’t notify a given thread, it tells the scheduler to pick a thread from a given lock’s wait set to notify).
Once the thread is woken up by a notify, it has to reacquire the lock in order to leave the wait method, because the thread is still inside of a synchronized method or block. That is what the quote means when it says the thread will need the lock to resume execution.
When a thread calls wait(), it's temporarily releasing the monitor (lock) of the object until it receives a notification from another thread. This way, a thread can willingly give control (that it has, in the first place) of the object's monitor to another thread. Take a look at the docs:
The invocation of wait() does not return until another thread has
issued a notification that some special event may have occurred —
though not necessarily the event this thread is waiting for (so always
invoke wait() inside a loop that tests for the condition being
waited for).
...
When wait() is invoked, the thread releases the lock and suspends
execution. At some future time, another thread will acquire the same
lock and invoke Object.notifyAll, informing all threads waiting on
that lock that something important has happened.

Why we must use "while" for checking race condition not "if"

I read the following code in "Thinking in java".
synchronized(obj)
{
while (condition_not_matched)
{
obj.wait();
}
//continue
dosomething();
}
What I think:
Use "if" is OK, because the "wait" means it must get the obj's lock monitor, and only one thread can executed here.
(1)Why here use "while (condition)" not "if" ?
(2)What happend when executed "obj.wait()"? Does the currrent thread release the lock of "obj"?
(3)And when another thread executed "obj.notify()", what happend of the previous thread (Did it refetch the lock of obj or not ?if yes, it must condition_not_matched , so "if" is enough.)
Am I wrong?
Using an if check instead of checking repeatedly in a loop is a mistake. There are multiple reasons to use the loop.
One is the "spurious wakeup", which means the wait method can return without the thread having been notified: it's not valid to infer, based on the thread exiting the wait method, that it must have gotten notified. This may not happen a lot but it is a possibility that has to be handled.
But the main reason is this one: When your thread waits it releases the lock. When it receives a notification it doesn't have the lock and has to acquire it again before it can exit the wait method. Just because the thread got notified doesn't mean it's next in line to get the lock. If the thread decides what to do based on something that happened when the thread didn't have ownership of the lock, multiple threads may have had the opportunity to act on the same shared object between the time the notify happened and the time that the thread got the lock, and the state of the shared object may not be what your thread thinks it is. Using a while loop allows the thread to check the condition it's waiting on again, with the lock held, confirming that the condition is still valid before it proceeds.
The need for the loop is explained in the Javadoc for the wait methods:
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.
To guard against this, after the wait() call returns, you have to check the condition again, and if it's false, go back and call wait() again instead of proceeding. The while loop accomplishes that.
When you call wait(), the object's lock is automatically released while waiting, and then acquired again before the method returns. This means that when another thread calls notify() on the object, the waiting thread can't immediately resume running, because the notifying thread still holds the object's lock and the waiting thread has to wait for it to be released. It also means that if there are several waiting threads and you call notifyAll(), the waiting threads can't all resume at once: one of the threads will get the lock and return from wait(), and when it releases the lock, then another of the threads can acquire it and return from wait(), and so on.
In some cases when multiple waiting threads are involved, a waiting thread may wake up, find that the condition is true, and do some stuff that ends up changing the condition back to false — all while holding the lock. Then, when it releases the lock (e.g. by calling wait() again), the next thread wakes up and finds that the condition is false. In this case, it isn't a spurious wakeup; the condition really did become true, but then became false again before the thread got a chance to check it.
For example: a producer thread adds several items to a queue and calls notifyAll() to wake up the consumer threads. Each consumer thread takes one item from the queue, then releases the lock while processing the item. But if there are more consumer threads than there were items added to the queue, some of the threads will wake up only to find that the queue is empty, so they just have to go back to waiting again.
Checking the condition in a while loop takes care of this situation in addition to handling spurious wakeups.
An if statement checks if an expression is true or false by running once, and then runs the code inside the statement only if it is true.
where as
A while condition continues to execute the code in the while statement untill the expression is true. Moreover while loops are more suitable to be used when you don't know how many times you may have to loop through the condition.
obj.wait() - causes the current thread to wait until another thread invokes the notify() method or the nofityAll() method for the respective object in this case. In case a timeout was passes as a parameter then the tread would wait till the certain amount of time has elapsed.
obj.notify() would wake up a single thread that was waiting on the respective objects monitor. The awakened thread will proceed only after the current thread relinquishes the lock on the object.

Confusion on Wait ,Notify and Sleep

I have a simple program which I am finding very confusing. The code snippet is as follows:
class Processor{
public void produce() Throws InterruptedException{
synchronized(this){
System.out.println("Producer Running...");
wait();
System.out.println("Resumed");
}
}
public void consume() Throws InterruptedException{
synchronized(this){
Thread.Sleep(2000);
System.out.println("Consumer Running... Press return key to return");
scan.nextLine();
notify();
Thread.sleep(5000);
}
}
Now my question is that , when we call wait() in the "produce" method the execution is immediately transferred to the "consume" method. (produce and consume are executed in separate threads). But when the notify(); is called in the "consume " method ,the execution does not immediately transfer. It waits for Thread.sleep(5000) to complete . why is this so ?
Well, the reason is quite simple.
When a thread calls wait() on certain object it goes into a waiting state and it stops executing (it is removed from scheduling). When waiting a thread releases all the monitors it has taken (and it needs to regain them after waking up)
When a thread calls notify() on certain object it wakes up another thread waiting over it, but it does not go into a waiting state itself, so it keeps running.
After your producer thread calls notify it keeps running and performing a five seconds sleep. While sleeping a thread retains all monitors that it has taken (you are inside a synchronized(this) block hence you have a monitor for "this" object). Scheduler cannot run the consumer thread that was just notified since it needs to readquire the monitor before resuming, and it wont be freed until your producer thread stops sleeping and gets out of the synchronized block
Although you seem to be missing some code needed for me to explain completely accurately, I'll do my best to provide an explanation that would be applicable even if my guess was incorrect.
wait() and notify() are methods called on a mutex object -- in this case, this.
wait() causes the currently executing thread to pause and give up that mutex (I think it's just the mutex that wait() is called on, could be all of them. Not sure), after which another thread can acquire the mutex and start executing. This is why you observe an immediate transfer of control when wait() is executed.
When notify() is called on a mutex, a thread waiting on that mutex wakes up and attempts to acquire the lock. However, it cannot do so until the lock is available -- in this case, until the lock (this) is released by the thread that calls notify() (the consumer thread). The mutex is only released once the consumer thread exits from the synchronized block, which is after the Thread.sleep(5000); call in your code. sleep() does not release any mutexes that the current thread has acquired, so the first thread has to wait until the second has finished sleeping and exited the synchronized block.
That is why wait() transfers control immediately, while notify() (in this case) has the currently executing thread finish its method before the formerly waiting thread can continue execution.
Assuming that you are calling both methods using the same object from difference threads.
If you want to don't wait 5000 miliseconds, use wait(5000) instead of Thread.sleep(5000).
The notify method, take one (random) previously waiting thread, that is waiting to acquire the lock (of an object) that the running/current thread has taken before, and mark it to resume as soon the current thread release the lock.
In your this case, it will release the lock and soon the Thread.sleep(5000) finish and leave the synchronized block.
Be aware, if you call produces or consume with diferents objects things will go totally diferent. I strongly suggest to read this article.
Hope it helps! As the good answers below!
The reason is that Thread.sleep(5000L) does not release the lock on the object's monitor while it's waiting, contrary to wait(5000L). This is specified in the Javadoc for Thread.sleep() :
... The thread does not lose ownership of any monitors.
Whereas the javadoc for Object.wait() specifies:
... This method causes the current thread (call it T) to place itself
in the wait set for this object and then to relinquish any and all
synchronization claims on this object...

Does the Java JVM guarantee the correct "wait" will be notified when calling "notify"?

According to a colleague, JVM does not guarantee that when calling "notify" on an object, the correct "wait" will be notified at that time. He says there can be a case when a previous notify which is not valid anymore is delivered at an invalid time.
Is this true? If so, how/why is this, and what use is the wait/notify mechanism if you cannot assume something as basic as this will work?
For java.lang.Object.notify, The Javadoc says:
Wakes up a single thread that is waiting on this object's monitor. If
any threads are waiting on this object, one of them is chosen to be
awakened. The choice is arbitrary and occurs at the discretion of the
implementation. A thread waits on an object's monitor by calling one
of the wait methods.
Here is a pattern to wait for a particular condition:
synchronized( lock ) {
while( conditionEvaluation( data )) {
lock.wait();
}
}
The counterpart should use java.lang.Object.notifyAll() to ensure the vivacity of the application. Even if today, it's only one waiter, after many evolutions of the software, it may be several waiters in the future, so notifyAll() is more robust than notify().
Each object that waits on an intrinsic lock will enter the lock's wait set. When you invoke notify on the lock object, one of the threads in its wait set will be chosen to resume work. The only guarantee that the JVM offers is that the waiting threads will be eventually notified. One of the main reasons for this non-deterministic behavior is the way suspended threads are chosen to run by the JVM, which is arbitrary. In addition however, locks in java implement a non-fair locking policy which permits thread barging. This simply means that it is permissible for new lock requests to jump ahead of the lock's wait set, it the lock is available at the time of the request. The justification behind this is that given substantial contention, there might be some (potentially significant) delay before choosing and resuming a suspended thread in the wait set and the time it actually runs. Any incoming lock request from a thread could therefore utilize this time delay to immediately run, in the hope that it will have released the lock by the time the resumed thread is ready to run. For example consider the following sequence of events:
Thread A that previously has acquired monitor X calls notify()
Thread B waiting on monitor X has chosen to be suspended (arbitrarily).
Thread C tries to acquire monitor X, sees that it is available and acquires it.
Thread C runs (despite thread B is currently in the process of being resumed)
Thread C finishes execution and releases monitor X, just before thread B is actually run.
Thread B is ready to run so it acquires the lock and starts execution.
It should be evident that between step 2 and 6 there exists some time interval where no threads are actually using the lock. Thread C barges in and utilizes the time interval as an optimization. The downside of this of course is the risk of not releasing the lock at the time thread B is ready to run, which at that time thread B will notice that the lock is unavailable and will enter the wait set again. Statistically however it can be proven that non-fair locking offers better performance in most situations.
As an aside note, you could use fair locks where waiting threads are resumed in the order they acquired the lock, but in practice this offers worse performance. Read more about this here: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/ReentrantLock.html
I hope this answers your question.
No it's not true. When a thread invokes notify, one waiting thread is awakened (if such a thread exists, otherwise notification is lost). Probably your colleague had in mind "spurious notify", which can awake a thread when in fact no other thread invoked notify or notifyAll. To filter "spurious notify", each notify invocation should accompanied with some change in monitored object state, and the waiting threads should check that state:
synchronized void up() {
counter++;
notify();
}
synchronized void down() {
while (counter==0) {
wait();
}
counter--;
}
Note checking state in down() is done before call to wait(), as it could be changed before the invocation and the notification is lost. In other words, the real information is passed with object's state, and wait/notify only help to avoid polling. Never rely on notifications without changing an object's state.

what does WAKEUP really mean in the notify/notifyall context?

some comments here have confused me! I thought I knew this and god knows I've written a ton of MT code, but its been a while and so....
FWIK notify/notifyall
notify: one thread is selected from the waitset and moved to the entryset to acquire monitor lock
notifyall : all threads are "notified" -
are they all moved to the entryset ?
Does this mean that they will all reacquire the lock as the lock holder releases it ? no more notify necessary ?
-all answers are just rephrasing what I've read elsewhere. I understand that only one of them can acquire the lock etc., my question this: once a thread is notified, it gets to wait on the monitor. right ? so need not be notified again if the thread holding the lock calls notify
For a precise specification of what happens, refer to the JLS section 17.8.2.
When a thread performs a notifyAll on a lock object, all other threads that are currently waiting are removed from the lock's waitset; i.e. they become runable. Each one then tries to reacquire the lock, and when that succeeds it returns from the wait(...) call.
Of course, the threads only succeed in acquiring the lock one at a time, and there are no guarantees of fairness. But eventually, they will all have acquired the lock.
Notification of waiting threads occur when notifyAll is called. All the waiting threads are removed from the object's wait set. Only one of the thread in the wait set is selected, of which there is no guarantee as to which thread is selected
The langspec has a section on Thread Notification
When notifyAll is called, all threads waiting on that lock are woken up, and one of them acquires the lock. The rest goes back to wait.
This may sound like notifyAll is a waste of resources, but AFAIR there used to be special tricky cases when calling notify may wake up the wrong thread, which can not handle the situation, resulting in a deadlock. Therefore it was recommended to use notifyAll always.
Since Java5 it is rarely necessary to worry about things like this, because the new concurrency utilities almost always handle these tasks better than wait and notify*, rendering them almost obsolete. The typical use of wait and notify* is in blocking queues, and now we have several ready made implementations of these - such as LinkedBlockingQueue and PriorityBlockingQueue - available in the class library.

Categories

Resources