I'm having the problem that sometimes a thread that I've started finishes before I call wait() on it. It seems that this causes my program to wait for something that is not going to happen again (notify()). How can I make sure not to wait for a finished thread?
void someFunction() {
MyThread thread = new MyThread();
thread.start();
// .. some stuff that takes sometimes quite long
synchronized(thread) {
try {
thread.wait();
} catch(InterruptedException e) {
// ..
}
}
}
If you read the JavaDocs for Thread, it tells you NEVER EVER use wait, notify, or notifyAll on Thread objects. You should use join()
You are looking at the "lost notification" problem. (I.e., you are not using wait() in the proper way.)
When you call foo.wait(), you should always be waiting for some condition that you can explicitly test. E.g., like this:
boolean condition;
synchronized(foo) {
while (! condition) {
foo.wait();
}
doSomethingThatRequiresConditionToBeTrue();
}
When you do anything that makes the condition true, it should look like this:
synchronized(foo) {
doSomethingThatMakesConditionTrue();
foo.notify();
}
When you do anything that makes the condition false, it should look like this:
synchronized(foo) {
doSomethingThatMakesConditionFalse();
}
Notice that:
Any code that touches the condition is synchronized, and always synchronized on the same object.
It is impossible for foo.wait() to be called when the condition is true.
The wait() is called in a loop.
Point (2) is crucial, because foo.notify() does not do anything at all if there is no other thread waiting to be notified. A notification that nobody's waiting for is "lost". The foo object does not remember that it was notified.
Point (3) is important for two reasons. The main one is, if thread A calls foo.wait(), and then thread B makes the condition true and calls foo.notify(); There's no guarantee that the condition will still be true when the wait() call eventually returns in thread A. Some other thread could have made the condition false again. This is a very real scenario in many applications.
The other reason why point (3) is important is that the Java Language Specification permits foo.wait() to return even when foo.notify() has not been called. That's called a "spurious wakeup", and allowing it to happen makes it easier to implement a JVM on certain operating systems.
Instead of wait(), you can use :
thread.join()
But i dont know the context of your situation.
Calling wait on the Thread works some of the time because when a thread terminates it sends a notification to every thread waiting for it. But if the thread has already terminated before your current thread calls wait, then no notification will ever occur.
The advice to use join is correct, and James Large’s answer is correct that your code should wait in a loop with a condition variable. That is exactly what join is doing, if you look in the code for java.lang.Thread.join (where join without an argument defaults to 0, wait(0) means wait without a timeout):
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
It has a loop where it tests the Thread’s alive flag, and if it is true then it proceeds to wait. If the thread is already terminated then the thread won’t wait, so the case where the current thread waits after the joined thread is finished cannot occur.
Related
Over here I'm trying to join a thread after it has been terminated, the code is working fine, but my question doesn't it should throw some error messageor any info?
public class MultiThreadJoinTest implements Runnable {
public static void main(String[] args) throws InterruptedException {
Thread a = new Thread(new MultiThreadJoinTest());
a.start();
Thread.sleep(5000);
System.out.println("Begin");
System.out.println("End");
a.join();
}
public void run() {
System.out.println("Run");
}
}
If you look at the source code of Thread::join you will notice that it calls Thread::join(timeout) method. And looking at the source code of this method we can see that it checks status of the thread in a loop by calling Thread::isAlive :
...
if (millis == 0 L) {
while (this.isAlive()) {
this.wait(0 L);
}
} else {
while (this.isAlive()) {
long delay = millis - now;
if (delay <= 0 L) {
break;
}
this.wait(delay);
now = System.currentTimeMillis() - base;
}
}
...
so if a Thread, that you call join on, is terminated - join will just return and do nothing.
I'm repeating info that is already in other answers and comments, but let me try and summarize, while adding explanation.
The point of thread.join() is to wait for the thread to terminate. That's what it tells you in the documentation for join:
Waits for this thread to die.
Waiting for a terminated thread to terminate is pretty straightforward (!), and there seems to be no logical reason why waiting for a terminated thread to terminate should be considered an error. You want to know when the thread finishes. It has.
More significantly, if the caller had to ensure that a thread had not terminated before waiting for it to terminate, that would create a timing window that every caller would have to compensate for. The trivial sequence
Thread t = new Thread(…);
t.start();
t.join();
would be prone to failure due to its inherent race hazard. In other words, that would be a bad way to design join.
No, Thread.join() will return instantly if the thread is already dead
Thread will start the execution. will print Run then thread will sleep for 5 seconds and will print Begin following by End
Output on the console:
Run
---- 5 seconds sleep ------
Begin
End
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 need to know how wait() and notify() works exactly? I couldn't achieve its working by using wait() and notify() as such. Instead if I use a while() loop for wait, it works properly. How is it so? Why can't I use just wait() and notify() simply?
have you read the documentation of the wait-notify functions ?
anyway, for the best way to achieve a wait-notify mechanism, use something like this (based on this website) :
public class WaitNotifier {
private final Object monitoredObject = new Object();
private boolean wasSignalled = false;
/**
* waits till another thread has called doNotify (or if this thread was interrupted), or don't if was already
* notified before
*/
public void doWait() {
synchronized (monitoredObject) {
while (!wasSignalled) {
try {
monitoredObject.wait();
} catch (final InterruptedException e) {
break;
}
}
wasSignalled = false;
}
}
/**
* notifies the waiting thread . will notify it even if it's not waiting yet
*/
public void doNotify() {
synchronized (monitoredObject) {
wasSignalled = true;
monitoredObject.notify();
}
}
}
do note, that each instance of this class should be used only once, so you might want to change it if you need to use it multiple times.
wait() and notify() are used in synchronized block while using threads to suspend and resume where left off.
Wait immediately looses the lock, whereas Nofity will leave the lock only when the ending bracket is encountered.
You can also refer this sample example:
public class MyThread implements Runnable {
public synchronized void waitTest() {
System.out.println("Before Wait");
wait();
System.out.println("After Wait");
}
public synchronized void notifyTest() {
System.out.println("Before Notify");
notify();
System.out.println("After Notify");
}
}
public class Test {
public static void main(String[] args) {
Thread t = new Thread(new MyThread());
t.start();
}
}
I think you are asking why does it work with while loop and does not without.
The answer is when your program calls wait() the operation system suspends your thread and activates (starts) another, and there will happen so called context switch.When OS suspend a thread it needs to save some "meta data" about your thread in order to be able to resume that thread later, PC register is what will answer your question.Basically PC (Program Counter) is a pointer to next instruction which the thread should do or is going to do, after being resumed a thread uses it to understand which instruction it was going to do when OS suspended him, and continues by that instruction (in this case, if you want to look at it by the means of Java program, the next instruction will be the next line after call to wait()).As written in "Java Concurrency in Practice"
Every call to wait is implicitly associated with a specific condition predicate. When calling wait regarding a particular
condition predicate, the caller must already hold the lock associated with the condition queue, and that lock must also
guard the state variables from which the condition predicate is composed.
Because your thread waits because some condition was not met (it should be) after returning to the method that it was suspended in, it needs to recheck that condition to see is it met yet.If condition is met it will not wait anymore, if it's not met it will call wait() again ( as it is in while loop).The important thing to know here is
PC (Program Counter) concept
and
The fact that a Thread that calls wait() on your method will not exit the method -> wait -> get resumed again -> call the method again, instead it will wait -> get resumed again -> continue from the point (instruction/line) where it was suspended (called wait())
We have two threads, Thread2 waits for Thread1 (receiving the messages from it)
class Thread1 .. {
run() {
synchronized(this) { some-work; notify(); }
}
}
class Thread2 .. {
run() {
while(true) {
synchronized(thread1) {
...
thread1.wait();
...
println("Got here"); // has received the notify() from Thread1
}
}
}
}
thread2.start() // thred2 is first to be ready to receive all messages from thread1
thread1.start()
After starting these threads in that sequence, we have the situation when thread2 is waiting for the notify() from thread1, and this will happen in couple of moments - the message "Got here" will be appeared.
But if I put a delay here:
class Thread2
run() {
while(true) {
sleep(1000); // the dalay
synchronized(thread1) { ..
}
Then the message 'Got Here' will be never appeared - because thread2 will miss the notify() from thread1 before the sycnronized(thread1) is reached - then we have a situation when Nothing To Wait.
The question is:
1.
Are these two lines atomic. Or better say is this gap between these two lines atomic?:
while(true) {
// gap
synchronized(thread1) {..thread.wait() ..}
}
2.
Or does it mean that we should not put any expression between while() and synchronized block? For example, we could have:
while(true) {
int a = 0; a++;
synchronized(thread1) {..thread.wait() ..}
Because it we have those expressions there then we have a risk of 'nothing-to-wait' situation?
wait and notify are not sufficient to create a signalling mechanism, for the reason that you've discovered: if you don't have any waiters, then the notify goes into the bit bucket.
A Semaphore is sufficient: if the sender returns the permit while the receiver is doing something else, then the receiver will immediately get that permit.
But, as some commenters said, a BlockingQueue is a better solution, as it means your code doesn't have to know anything about threading.
No gap between lines is "atomic", the concept of atomicity does not apply here.
If you want to avoid missing the notify, start thread1 in the body of thread2's run method.
Actually, you ask whether this could happen without the sleep(), right? Imho the answer is yes. While the "gap" is just that - nothing - the loop itself consists of actual instructions as well. In between them, the threads can get switched. IMHO it is also not garantueed that you reach Thread2.run before Thread1.run just because you started Thread2 first. I'm not sure how to solve this problem, though. Maybe have Thread1 wait for Thread2 somehow?
public class Ex4 extends Thread {
boolean ans;
boolean change=false;
public boolean isPrime(long n, double maxTime) throws RuntimeException {
final Thread a;
Thread b;
final RuntimeException e;
final long num = n ;
final double mtime = maxTime;
a = new Thread(){
public void run(){
try{
ans = Ex4_tester.isPrime(num);
change=true;
}
catch ( RuntimeException exp){
throw exp;
};
}
};
a.start();
try {
sleep((long)mtime);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
if(a.isAlive()){
a.interrupt();
}
if(a.isInterrupted()){
throw new RuntimeException("time for check exceeded");
}
return ans;
}
}
all works fine, except sometimes Ex4_tester.isPrime goes into infinite loop (its ok, it should do that).
the problem that even though the thread gets interrupted the process keeps running and the thread doesnt actually stop
A thread getting interrupted doesn't stop it. It just causes the thread to get out of certain wait and sleep states. To have the thread exit an infinite loop based on input from another thread, put an explicit check against an Atomic<> in the loop and have the control thread modify the state of the atomic variable to where thread 'a' will exit the loop.
Only certain methods like Object.wait() will throw InterruptedException. If your thread doesn't call any of those methods, it won't get interrupted.
In other words, you can't asynchronously interrupt a Java thread. Very few threading systems support asynchronous interruption.
The most easy way is to set your thread to be daemon, that is call a.setDaemon(true) before start. That will make your process will be ended if this is only thread that stayed started.
If you want to interrupt your thread read this documentation for interrupt method
interrupt method causes InterruptedException only when the thread is in certain points of execution (such as sleep). Your code has invalid cancellation policy. You should consider another way of stopping your thread.
An interrupt requires an explicit check at a point where it is safe by design to interrupt a thread. If you don't perform this check (or call a method which does) the thread will keep running.