This question already has an answer here:
Who notifies the Thread when it finishes?
(1 answer)
Closed 4 years ago.
Not sure why b.wait() doesn't wait the main thread. If we create a dummy object, Object a = new Object(); it waits. If I extend ThreadA with Thread and create a instance for ThreadA and lock using ThreadA reference it works. But why the below wait() doesn't work
package com.aircell;
public class ThreadA{
public static void main(String[] args){
ThreadB b = new ThreadB();
b.start();
System.out.println("who is this thread");
synchronized(b){
try{
System.out.println("Waiting for b to complete...");
b.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + b.total);
}
}
}
class ThreadB extends Thread{
int total;
#Override
public void run(){
synchronized(this){
for(int i=0; i<100 ; i++){
total += i;
}
}
System.out.println("done thread");
}
}
First of all: If I try out your class Here[TM] I get the following output:
who is this thread
Waiting for b to complete...
done thread
Total is: 4950
So it does work which is a bit surprising, but I think the following sentence in the Javadoc of wait seems to happen here:
As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop.
The following change should give you the behavior you wanted to implement:
public class ThreadA{
public static void main(String[] args){
ThreadB b = new ThreadB();
System.out.println("who is this thread");
synchronized(b){
b.start();
try{
System.out.println("Waiting for b to complete...");
while (!b.finished) {
b.wait();
}
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + b.total);
}
}
}
class ThreadB extends Thread{
int total;
boolean finished;
#Override
public void run(){
synchronized(this){
try {
for(int i=0; i<100 ; i++){
total += i;
}
}
finally {
finished = true;
this.notifyAll();
}
}
System.out.println("done thread");
}
}
Wonderful question. Took me several hours to figure this out.
When a thread finishes execution, the thread object (in this case, object - "b") is notified by the JVM.
So, in the main thread, if the execution has reached b.wait() before ThreadB finishes, then an implicit b.notify() is called which notifies the main thread. The sequence that's happening in your code is either of the following 2 :
Case I :
b.start() is called.
However, before threadB can execute, main thread enters synchronized block, acquires lock, and calls b.wait().
b.wait() releases the lock, main thread is descheduled, and threadB begins execution.
threadB completes execution and lock is released.
Since threadB is completed, notify() is called on the Thread object. i.e., JVM triggers an implicit b.notify()
Main thread is awoken and completes it's task.
Case II :
b.start() is called.
threadB execution begins before main thread can acquire lock. Main thread is blocked on synchronized(b)
threadB completes execution and lock is released.
Main thread acquires lock and enters synchronization block and b.wait() is called.
Since threadB is completed, notify() is called on the Thread object. i.e., JVM triggers an implicit b.notify()
b.wait() releases the lock, main thread is descheduled, and 2nd thread begins execution.
Main thread is awoken and completes it's task.
However, if you add a delay in the main thread. Sufficient enough for ThreadB to finish before main thread can execute b.wait(), you will see that the main thread waits. If you put Thread.sleep(2000);
wait() method can not guarantee the execution to wait for first to finished but if you want one thread to fin
Related
I was trying to use java.lang.Object.wait() method and have written 3 different sample codes wherein I am getting different behavior of wait() method.
sample 1)
class Main {
public static void main(String[] args) throws InterruptedException {
ThreadB b = new ThreadB();
b.start();
Thread.sleep(10000);
synchronized (b) {
System.out.println("main thread trying to call wait() method"); //--> 3
b.wait();
System.out.println("main thread got notification");
System.out.println(b.total);
}
}
}
class ThreadB extends Thread {
int total = 0;
public void run() {
synchronized (this) {
System.out.println("child thread starts calculation"); //--> 1
for (int i=0; i<=100; i++) {
total = total + i;
}
System.out.println("child thread trying to give notification"); //--> 2
this.notify();
}
}
}
sample 2)
public class Main{
public static void main (String[] args) throws InterruptedException {
Thread t = new Thread();
t.start();
System.out.println("X"); //--> 1
synchronized(t) {
System.out.println("starting to wait"); //--> 2
t.wait(10000);
System.out.println("waiting on t"); //--> 3
}
System.out.println("Y"); //--> 4
}
}
sample 3)
public class Main{
public static void main (String[] args) throws InterruptedException {
Thread t = new Thread() {public void run()
{System.out.println("I am the second thread.");}};
t.start();
System.out.println("X"); //--> 1
synchronized(t) {
Thread.sleep(4000);
System.out.println("starting to wait"); //--> 2
t.wait(10000);
System.out.println("waiting on t"); //--> 3
}
System.out.println("Y"); //--> 4
}
}
In sample 1)
main thread goes in waiting state forever as it has called b.wait() method and there is no thread to provide notify() or notifyAll() on object b. There was child thread that has already been terminated before main thread called b.wait() method.
This output is what I expected.
In sample 2)
main thread goes in waiting state for 10 seconds (t.wait(10000);) after printing
X
starting to wait
after 10 seconds main thread executes
waiting on t
Y
This is also my expected output.
In sample 3)
main thread is NOT going in waiting state (t.wait(10000);) even though it is sure that child thread would have been terminated by the time main thread called t.wait(10000);
So why it didn't wait ? and straightaway executed
starting to wait
waiting on t
Y
This is NOT my expected output.
For the first two examples your expectations seem correct. In the third example it seems reasonable to expect that t will finish before the main thread starts waiting, and then the main thread will hang until it times out.
But as you observed, that isn't what happens.
A waiting thread doesn't stop waiting unless interrupted or notified (except for spurious wake ups, but those are the result of unpredictable race conditions; the behavior in the posted code happens reliably, so I think spurious wakeups can be excluded here).
Since there is nothing interrupting the main thread, and its wait is cut short and we've ruled out spurious wakeups, it must be receiving a notification. There is only one thing that can provide the notification, and that is the t thread.
For t to notify the main thread it must have been alive at the time that t started waiting. So what is keeping it around?
There is some not-well-known behavior that occurs when a thread terminates. The API documentation for Thread.join says:
This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.
What happens is:
1) t prints its output and is on the way out of its run method.
2) There is a race between t and the main thread to acquire the lock on t. t needs it to call notifyAll, main needs it to enter the synchronized block. The main thread happens to grab the lock first.
3) t hangs around until it can acquire the lock.
4) The main thread enters the wait method (releasing the lock).
5) The t gets the lock and calls t.notifyAll.
5) The main thread is notified and leaves the wait method (reacquiring the lock).
Some lessons:
Don't synchronize on threads (this is a good example of why the API docs say not to do this, here you inadvertently delayed a thread from dying in a timely fashion).
If a thread isn't waiting, it doesn't get notified. If a thread starts waiting after the notification has already happened, that notification is lost.
Don't rely solely on notifications (it makes your code vulnerable to race conditions), instead use notifications along with some condition that the other thread can set. Call wait in a loop with a test condition. If you see the Thread.join source code, it is a good example, it looks something like:
while (isAlive()) {
wait(0);
}
Don't sleep while holding a lock. It makes the system less responsive for no benefit.
Be very careful about making assumptions about the order things happen in.
class ThreadA {
public static void main(String[] args) {
ThreadB b = new ThreadB();
b.start();
synchronized (b) {
try {
System.out.println("Waiting for b to complete...");
b.wait();
} catch (InterruptedException e) {
}
System.out.println("Total is: " + b.total);
}
}}
class ThreadB extends Thread {
int total;
public void run() {
synchronized (this) {
for (int i = 0; i < 100; i++) {
total += i;
}
notify();
}
}}
I am unable to understand the code flow and how run method is being called in the above programs.
When the object is of class ThreadB then why main() thread of ThreadA is able to synchronize object b. Apart from that when wait() is encountered by the main() thread, how the executions shifts to run() in ThreadB.
Why does main() reaches to the synchronized block even before ThreadB's run() is able to execute.
Your program has a race condition.
After main() calls b.start() there are two threads running, unsynchronized, and they race to lock (i.e., synchronize on) the b object. There is no way to predict which thread will lock it first.
If the main() thread locks it first, then it will call b.wait(). That will temporarily unlock the b object, and allow the other thread to run. The other thread will do its work, call b.notify() and exit the synchronized block. As soon as it exits, the main() thread will be able to return from the wait() call.
If the second thread is first to lock the b object, the behavior will be different: It will do its work, call notify(), and return. But the notify() call will do nothing in that case because the main() thread will be blocked trying to enter the synchronized block. It won't be waiting in the b.wait() call, and notify() doesn't do anything if there isn't any other thread waiting.
So what will happen next in that case is, when the ThreadB thread leaves the synchronized block, the main() thread will be able to enter it and call wait(). The program will hang at that point because the ThreadB thread has already finished its work and died. There's no other thread left to call notify().
We call it a race condition when two (or more) threads race to do something, and the output of the program depends on which one gets there first.
Apart from that when wait() is encountered by the main() thread, how the executions shifts to run() in ThreadB.
Before invoke wait()
If it will invoke wait method next step, It means main thread hold monitor of object b currently. And if threadB want to execute run() method it will be blocked for waiting monitor of b which is hold by main thread.
invoke wait()
It means main thread release monitor, come into wait status, and advice thread scheduler re_dispatch. Then ThreadB can get monitor and make thing.
notify()
after finishing its job, threadB invoke notify() to wake up a single thread that is waiting on this object's monitor, here is main thread. And main thread will go on doing its work.
I'm looking at some notify/wait examples and came across this one. I understand a synchronized block essentially defines a critical section, but doesn't this present a race condition? Nothing specifies which synchronized block is entered first.
public class ThreadA {
public static void main(String[] args){
ThreadB b = new ThreadB();
b.start();
synchronized(b){
try{
System.out.println("Waiting for b to complete...");
b.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + b.total);
}
}
}
class ThreadB extends Thread {
int total;
#Override
public void run(){
synchronized(this){
for(int i=0; i<100 ; i++){
total += i;
}
notify();
}
}
}
Output per website:
Waiting for b to complete...
Total is: 4950
Right, it's not guaranteed which thread will execute first. The thread b could do its notification before the main thread ever starts to wait.
In addition to that, a thread can return from wait without having been notified, so setting a flag and checking it before entering the wait technically isn't good enough. You could rewrite it to something like
public class ThreadA {
public static void main(String[] args) throws InterruptedException {
ThreadB b = new ThreadB();
b.start();
synchronized(b){
while (!b.isDone()) {
System.out.println("Waiting for b to complete...");
b.wait();
}
System.out.println("Total is: " + b.total);
}
}
}
class ThreadB extends Thread {
int total;
private boolean done = false;
#Override
public void run(){
synchronized(this){
for(int i=0; i<100 ; i++){
total += i;
}
done = true;
notify();
}
}
public boolean isDone() {return done;}
}
so that the main thread will wait until b is done with its calculation, regardless who starts first.
By the way, the API documentation recommends you not synchronize on threads. The JDK synchronizes on threads to implement Thread#join. A thread that terminates sends a notifyAll that anything joining on it receives. If you were to call notify or notifyAll from a thread you've acquired the lock on, something joining on it could return early. One side effect of this here is that if you remove the notify the code works the same way.
Yes, it's a race condition. Nothing prevents ThreadB from starting, entering its run method, and synchronizing on itself prior to ThreadA from entering its synchronized block (thus waiting indefinitely). However, it's very unlikely to ever happen, considering the time it takes for a new thread to begin execution.
The easiest, and most recommended way to handle this type of situation is to not write your own implementation, but opt to use a callable/future provided by an Executor.
To fix this particular case without following standards:
Set a boolean 'finished' value set at the end of ThreadB's synchronized block.
If the boolean 'finished' is true after entering the synchronized block, then you should not call wait.
Yes - it is a race as to which thread enters which synchronized block first. For most scenarios of the race, the output and the answer will be the same. For one, however, the program will deadlock:
Main starts calls b.start() and immediately schedules out.
Thread B starts, enters synchronized, calls notify().
Main enters its synchronized block, calls wait()
In this case, main will wait forever since thread b called notify before main blocked on wait().
That said, this is unlikely - but with all threading you should conclude that it will happen and then at the worst possible time.
For the code below, the expected output is:
Waiting for b to complete...
Total is: 4950
How come it can't print the Total is.. first then Waiting for b.. after? I'd think b.start() could be executed first in some cases, then it holds onto ThreadB's lock with synchronized(this) in ThreadB.run() thus blocking main from entering in synchronized(b).
Is anything wrong with what I just stated?
public class ThreadA {
public static void main(String[] args) {
ThreadB b = new ThreadB();
b.start();
synchronized(b) {
try{
System.out.println("Waiting for b to complete...");
b.wait();
} catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println("Total is: " + b.total);
}
}
}
class ThreadB extends Thread {
int total;
#Override
public void run() {
synchronized(this) {
for(int i=0; i<100 ; i++) {
total += i;
}
notify();
}
}
}
The two output statements will always have the same order, because they are executed on one thread. Waiting for another thread to finish between them will not change their execution order.
If you put the "Total is ..." output to the end of b's run() then there might be a chance for seeing indeterministic orders of the outputs.
EDIT - Please also note #Holger 's comment to this answer:
[...] in the unlikely, but still possible case that ThreadB’s synchronized block is executed first, its notify() call will have no effect as no-one is waiting yet and then, ThreadA’s wait() call may hang forever as there will be no subsequent notification.
Actual problem over here is you have only one thread "b" over here and you are calling wait() on b which is taking b thread to WAIT state and there is no other thread which can notify this thread and bring b back to runnign state.
public class ThreadA {
public static void main(String[] args){
ThreadB b = new ThreadB();
b.start();
synchronized(b){
try{
System.out.println("Waiting for b to complete...");
b.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + b.total);
}
}
}
class ThreadB extends Thread{
int total;
#Override
public void run(){
synchronized(this){
for(int i=0; i<100 ; i++){
total += i;
}
notify();
}
}
}
In the example above, an object, b, is synchronized. b completes the calculation before Main thread outputs its total value.
output:
Waiting for b to complete...
Total is: 4950
If the main thread gains the lock of b first, then the main thread will execute the synchronized(b) block. Will b.wait() suspend thread b(thread b doesn't run yet)? If yes, how can this code produce the result?
If thread b gains the intrinsic lock first, what's the result of notify()?
When you use notify/wait you should do this based on a state change. if you do not, you open yourself to a number of issues.
If you notify() when there is no thread waiting, the notification is lost. A wait() coming later might wait forever.
If you wait(), it can wake spuriously i.e. it doesn't mean there was a notify.
The solution is to either;
not use notify/wait as it was largely replaced 10 years ago by the
concurrency libraries
have notify() thread change a field/state and have wait() thread
check this in a loop.
As James Large notes, wait()ing is not fair in the sense there is no guarantee the first thread to wait will be the next one notified.
Also you can't change state without holding the same synchronized lock and expect it to behave correctly all the time.
Will b.wait() suspend thread b(thread b doesn't run yet)? If yes, how
can this code produce the result?
No, it's the synchronized(this) (where this refers to the same object as b) that will block the other thread. Once b.wait is invoked, the monitor on the object referenced by b is released, the main thread goes to sleep, and the other thread acquires the monitor, entering the synchronized block.
If thread b gains the intrinsic lock first, what's the result of
notify()?
There are no threads waiting on b/this, so notify will basically do nothing. When your other thread releases the monitor, your main thread will acquire it and call wait, waiting forever since there's nothing else to notify it.