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.
Related
public class SimpleThreads {
// Display a message, preceded by the name of the current thread
static void threadMessage(String message) {
String threadName = Thread.currentThread().getName();
System.out.format("%s: %s%n", threadName, message);
}
private static class MessageLoop implements Runnable {
public void run() {
String importantInfo[] = { "Mares eat oats", "Does eat oats","Little lambs eat ivy", "A kid will eat ivy too" };
try {
for (int i = 0; i < importantInfo.length; i++) {
threadMessage(importantInfo[i]);
}
} catch (Exception e) {
threadMessage("I wasn't done!");
}
}
}
public static void main(String args[]) throws InterruptedException {
threadMessage("Starting MessageLoop thread");
Thread t = new Thread(new MessageLoop());
t.start();
threadMessage("Waiting for MessageLoop thread to finish");
}
}
OUTPUT
main: Starting MessageLoop thread
main: Waiting for MessageLoop thread to finish
Thread-0: Mares eat oats
Thread-0: Does eat oats
Thread-0: Little lambs eat ivy
Thread-0: A kid will eat ivy too
Here at first the main thread printed the message 'main: Starting MessageLoop thread'. After that I started Thread-0 OR MessageLoop thread.
Thread t = new Thread(new MessageLoop());
t.start();
But before starting/printing Thread-0 messages its printing 'main' thread message 'main: Waiting for MessageLoop thread to finish' and Thread-0 was executed after that only. Why ?
That behavior is normal and must be expected, although you can't count on it either way.
You seem to expect the main thread to wait for the second thread to be running. This, however, is not the case with your code. The point of starting a second thread is concurrent execution, implying that that you can't count on the sequence of execution just because the statements in code are sequential.
If you want the main thread to wait for the other thread to execute, then you need to synchronize them. This, however, defeats the purpose of starting the second thread in your case. If you wanted main thread to wait for second thread, you could then just call the method without starting the second thread.
Googling "java concurrency" led to, among other pages, this one. That doc explains a lot of these concepts.
Because invoking start() on a thread doesn't make the thread effectively executed right now.
It is the way which works multithreading.
From Thread.start() documentation :
Causes this thread to begin execution; the Java Virtual Machine calls
the run method of this thread.
The result is that two threads are running concurrently: the current
thread (which returns from the call to the start method) and the other
thread (which executes its run method).
The main thread is currently executed as you invoke t.start(); .
The thread will at a time be paused by the JVM but you don't master when.
In your specific case, you will get a reproducible behavior.
As after t.start();, you have a statement very fast to execute :
threadMessage("Waiting for MessageLoop thread to finish");
it never doesn't let the main thread to be paused and the new thread to be effectively run.
Add after t.start();, some statements that take more time to be executed in the main thread or invoke sleep() on it and you should see a different behavior.
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 was expecting the second thread in the following example to hang, since it waits on an object with no corresponding notify. Instead, it falls through to the println, presumably due to a spurious wakeup.
public class Spurious {
public static void main(String[] args) {
Thread t1 = new Thread() {
public void run() {
System.out.println("Hey!");
}
};
Thread t2 = new Thread() {
public void run()
{
try {
synchronized (t1) {
t1.wait();
}
} catch (InterruptedException e) {
return;
}
System.out.println("Done.");
}
};
t1.start();
t2.start();
}
}
Output:
Hey!
Done.
On the other hand, if one removes the "Hey!" println from the first thread, the second thread will indeed hang. This happens on both MacOS and Linux.
Any idea why?
This is not a spurious wakeup, a spurious wakeup is caused by a race condition in the JVM. This is a race condition in your code.
The println keeps thread1 alive just long enough that thread2 can start waiting before thread1 terminates.
Once thread1 terminates it sends a notification to everything waiting on its monitor. thread2 receives the notification and ceases waiting.
Removing the println reduces the time needed for thread1 to finish so that thread1 has already finished by the time thread2 can start waiting on it. thread1 is no longer alive and its notification has already occurred before thread2 started waiting, so thread2 waits forever.
That threads send a notification when they die is documented in the API for Thread#join:
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.
(For a thread to call notifyAll it has to hold the lock, if the other thread grabs the lock, it can keep the terminating thread alive and delay the notifyAll until the terminating thread can acquire the lock.)
The moral (well, one of the morals) is to always wait in a loop with a condition variable, see the Oracle tutorial. If you change Thread2 to look like this:
Thread t2 = new Thread() {
public void run()
{
try {
synchronized (t1) {
while (t1.isAlive()) {
t1.wait();
}
}
} catch (InterruptedException e) {
return;
}
System.out.println("Done.");
}
};
then thread2 should exit regardless of whether thread2 can start waiting before thread1 finishes.
Of course this is total toy example territory:
Don't extend Thread, use Runnable or Callable.
Don't lock on threads.
Don't start Threads, use Executors.
Prefer higher level concurrency constructs to wait/notify.
You're waiting on a Thread object. That's bad practice, that is explicitly discouraged in the javadoc of Thread (Thread.join, precisely).
The reason is that when you call thread.join() to block until the thread stops running, you're actually waiting on the thread. And when the thread stops running, it notifies in order to unblock all the callers of join().
Since you waited on the thread, you're implicitly being notified when the thread stops running.
According to what I understood, when I use a synchronized block it acquires the lock on an object and releases it when the code block is done executing. In the following code
public class WaitAndNotify extends Thread{
long sum;
public static void main(String[] args) {
WaitAndNotify wan = new WaitAndNotify();
//wan.start();
synchronized(wan){
try {
wan.wait();
} catch (InterruptedException ex) {
Logger.getLogger(WaitAndNotify.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("Sum is : " + wan.sum);
}
}
#Override
public void run(){
synchronized(this){
for(int i=0; i<1000000; i++){
sum = sum + i;
}
notify();
}
}
}
what happens if the synchronized block inside the run method acquires the lock first? Then the synchronized block inside the main method has to wait (not because of the wait(), because the other thread acquired the lock). After the run method is done executing, won't the main method enter its synchronized block and wait for a notify which it will never get? What did I misunderstand here?
wait() implicitly exits the respective monitor temporarily and re-enters it upon returning:
See wait()
The current thread must own this object's monitor. The thread releases
ownership of this monitor and waits until another thread notifies
threads waiting on this object's monitor to wake up either through a
call to the notify method or the notifyAll method. The thread then
waits until it can re-obtain ownership of the monitor and resumes
execution.
That's why and how this sort of synchronization does work at all.
Yes, it's possible to perform a notify() before a wait() causing a hung thread, so you need to be careful that it can't happen.
For that reason (and others) it's generally better to use the higher level constructs of java.util.concurrent, since they generally give you less possibilities to shoot yourself in the foot.
You won't see the 'waiting forever' issue here, because you are calling the version of wait() with a timeout; so, after 5 seconds it returns even if it doesn't receive a notify. The 'wait forever' version of the wait() call could indeed exhibit the problem you describe.
You've got two threads here: your WaitAndNotify (WAN) thread, and Java's main execution thread. Both are vying for the same lock.
If the WAN thread gets the lock first, the main thread will be blocked. Being in a blocked state is NOT the same as being in a wait state. A thread in the wait state will wait for notification before moving forward. A thread in the blocked state will actively try to get the lock when it becomes available (and keep trying until it does).
Assuming the run method executes normally, it will call notify(), which will have no effect because no other threads are currently in a wait state. Even if there were, WAN still holds the lock until it exits the synchronized block of code. Once WAN exits the block, THEN Java would notify a waiting thread (if there was one, which there is not).
At this point, the main execution thread now obtains the lock (it is no longer blocked) and enters the wait state. Now you've used the version of wait that will wait up to 5000 milliseconds before continuing. If you used the vanilla version (wait()) it would wait forever because no other process would notify it.
Here is a version of the example program changed to introduce a loop that tests a condition variable. This way you avoid bad assumptions about the state of things after a thread re-acquires a lock upon waking from a wait, and there's no order dependence between the two threads:
public class W extends Thread {
long sum;
boolean done;
public static void main(String[] args) throws InterruptedException {
W w = new W();
w.start();
synchronized(w) {
while (!w.done) {
w.wait();
}
// move to within synchronized block so sum
// updated value is required to be visible
System.out.println(w.sum);
}
}
#Override public synchronized void run() {
for (int i = 0; i < 1000000; i++) {
sum += i;
}
done = true;
// no notify required here, see nitpick at end
}
}
It's not sufficient to wait on a notification, for the reason you point out (order dependence, where you're relying on a race condition hoping one thread acquires the monitor before another) as well as for other reasons. For one thing, a thread can wake up from waiting without ever having received a notification, you can't assume that there was a notify call at all.
When a thread waits, it needs to do so in a loop, where in the test on the loop it checks some condition. The other thread should set that condition variable so the first thread can check it. The recommendation that the Oracle tutorial makes is:
Note: Always invoke wait inside a loop that tests for the condition being waited for. Don't assume that the interrupt was for the particular condition you were waiting for, or that the condition is still true.
Other nitpicks:
As your example is written, the JVM is not required to make the changes to your sum variable visible to the main thread. If you add a synchronized instance method to access the sum variable, or access the sum within a synchronized block, then the main thread will be guaranteed to see the updated value of sum.
Looking at your logging, there is nothing SEVERE about an InterruptedException, it doesn't mean anything went wrong. An InterruptedException is caused when you call interrupt on a thread, setting its interrupt flag, and that thread is either currently waiting or sleeping, or enters a wait or sleep method with the flag still set. In my toy example at the top of this answer I put the exception in the throws clause because I know it's not going to happen.
When the thread terminates it issues a notifyAll that anything waiting on that object will receive (again, that's how join is implemented). It's better style to use Runnable instead of Thread, partly because of this.
In this particular example it would make more sense to call Thread#join on the summing thread, rather than calling wait.
Here's the example re-written to use join instead:
public class J extends Thread {
private long sum;
synchronized long getSum() {return sum;}
public static void main(String[] args) throws InterruptedException {
J j = new J();
j.start();
j.join();
System.out.println(j.getSum());
}
#Override public synchronized void run() {
for (int i = 0; i < 1000000; i++) {
sum += i;
}
}
}
Thread#join calls wait, locking on the thread object. When the summing thread terminates it sends a notification and sets its isAlive flag to false. Meanwhile in the join method, the main thread is waiting on the summing thread object, it receives the notification, checks the isAlive flag, and realizes it doesn't have to wait anymore, so it can leave the join method and print the result.
I am trying to achieve this: Created two different threads, one prints odd numbers, one prints even numbers. Once one thread prints a number, it has to wait for the other thread and so on, that is one-after-other.
To achieve this, i am using synchronized block along with wait() and notify().
I am creating a class whose's object will be used to pass to synchronized block in both the threads.
Here is the code:
--> This is used object which will be passed to synchronized block.
package com.vipin.multithread.variousdemos;
public class SyncObject {
public SyncObject () {
}
}
Odd Thread:
package com.vipin.multithread.variousdemos;
public class OddThread implements Runnable {
private Thread t;
int index=0;
SyncObject so=null;
int odd_nums[] = {1,3,5,7,9};
public OddThread(SyncObject so) {
t = new Thread(this,"Odd Thread");
this.so = so;
t.start();
}
public Thread getThreadInstance() {
return t;
}
#Override
public void run() {
while (true) {
synchronized(so) {
System.out.println("Odd num is --->" + odd_nums[index]);
try {
so.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
index++;
so.notify();
if(index>=5) {
return;
}
}
}
}
}
Even Thread: UPDATE
package com.vipin.multithread.variousdemos;
public class EvenThread implements Runnable {
private Thread t;
int index=0;
SyncObject so=null;
int even_nums[] = {2,4,6,8,10};
public EvenThread(SyncObject so) {
t = new Thread(this, "Even thread");
this.so = so;
t.start();
}
public Thread getThreadInstance() {
return t;
}
#Override
public void run() {
while(true) {
synchronized(so) {
System.out.println("Even num is --->" + even_nums[index]);
so.notify(); <-- Here we are notifying.
try {
so.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
index++;
//so.notify(); <-- commented out.
if(index>=5) {
break;
}
}
}
}
}
Main Application:
package com.vipin.multithread.variousdemos;
public class EvenOddDemo {
public static void main(String[] args) throws InterruptedException {
SyncObject so = new SyncObject();
OddThread ot = new OddThread(so);
EvenThread et = new EvenThread(so);
System.out.println("\nIn main thread");
Thread.sleep(1000000000);
System.out.println("Exiting main thread...");
}
}
---> As seen in the code, I am creating two threads to print even and odd numbers. I am using synchronized block, and passing object of type ==> SyncObject.
SyncObject I am passing as argument to these different threads in main.
However, this programs halts, i.e stuck only first statement gets executed, and then it waits forever:
Here is the output:
Odd num is --->1
In main thread
Even num is --->2
I am not able to understand why this program waits for ever, I am using SAME object on which we are invoking synchronized(), wait() and notify(). As per my understanding, it should work, not sure why this is not working.
Any clues as to why this is waiting forever.
UPDATE:
I did some changes in the code, UPDATE and it works fine.
I still have some doubt. Does notify() be called by the thread even if it has not locked the monitor, like in my case after i updated the code.
Sequence of events:
Odd thread gets executed first, then it calls wait() <-- it releases the monitor and now in sleep mode.
Even thread runs, prints msg, and calls notify() <-- here i am not having clear understanding.
When Even thread calls notify(), at that point it has the monitor, so when it calls notify(), does is still own the monitor?
Now, after Even thread calls notify(), then Odd thread gets notified, and hence it starts execution from the point it was sleeping. It is doing some execution and calls notify(), at that points I presume Odd thread is NOT owning the monitor, it calls notify(). So, my question is, does notify() work same whether or not the thread owns the monitor?
It is only when one do the code, one really understands this. I read book and i felt i understood everything, and seems i am back to square one!
The problem here is simply that both threads go straight into wait. Thread 1 gets so, prints value then waits. Thread 2 then gets so, prints value then waits. So both are sleeping away, since nobody is there to notify them. So, a simple fix would be to do so.notify(), right before so.wait(). Then they're not infinitely waiting.
EDIT
Odd thread starts, executes & then waits. Then even thread starts, executes, notifies & then waits. Even thread holds the lock over the monitor until it goes into wait.
When the even thread called on notify, the odd thread awakens & polls for the lock. Once the even thread goes into wait (& releases the lock), then the odd thread can obtain the lock.
If the even thread had not called on notify, then the odd thread would continue to sleep. The even thread would have gone to wait & released the lock. No thread is polling or attempting to obtain the lock, hence the program remains in the suspended state.
The documentation also provides a similar explanation. I hope that clears your doubts.