I am looking in some puzzles for threads and I can't figure out why the following consistently prints 999999
:
class Job extends Thread {
private Integer number = 0;
public void run() {
for (int i = 1; i < 1000000; i++) {
number++;
}
}
public Integer getNumber() {
return number;
}
}
public class Test {
public static void main(String[] args)
throws InterruptedException {
Job thread = new Job();
thread.start();
synchronized (thread) {
thread.wait();
}
System.out.println(thread.getNumber());
}
}
There is no notify
on the same lock (and spurious wakeup seem to be ignored).
If a thread finishes does a notify get signalled or something?
How come main
prints the result and not get "stuck" waiting?
In the Javadoc for Java 7 Thread.join(long)
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.
Using a Thread directly this way is considered bad practical. Note: wait() could end for any number of reasons, possibly spuriously.
Based on a puzzler related to @Voo's comment. The point is you shouldn't play with the internal behaviour of Thread as this is more likely to lead to confusion.
public static String getName() {
return "MyProgram";
}
public static void main(String... args) {
new Thread() {
public void run() {
System.out.println("My program is " + getName());
}
}.start();
}
What does this program print?
For clarification, I have modified your code to this:
Job thread = new Job();
thread.start();
final Object lock = new Object();
synchronized (lock) { lock.wait(); }
System.out.println(thread.getNumber());
Now it blocks. That's a first-hand confirmation of what @Nitram has explained in his answer. If you care to have a look at the Thread
implementation code, it will be quite obvious why this is the observed behavior.
NOTE: This answer has been edited extensively.
The reason for this behaviour is, that "someone" is calling notifyAll
internally. This "someone" is the JVM itself as you can "see" in the C sources here:
http://hg.openjdk.java.net/jdk7/hotspot/hotspot/file/f95d63e2154a/src/share/vm/runtime/thread.cpp
In line 1531 the method ensure_join
calls notifyAll
. This is the counterpart to the wait
calls in java.lang.Thread#join
(as noted by Marko and others).
ensure_join
in turn is called in line 1664 in the method JavaThread::exit
.
Since this is "internal bookkeeping" nobody should rely on this behaviour.
Simply put a Thread
notifies all waiting threads once the execution of the threads ends. Its not the proposed why to do this, but it works. To synchronize on the end of a thread rather use Thread.join
.
A thread object is automatically notified when the thread finishes, that's why the main thread doesn't get stuck.
Well....notify serves purpose of premature notifying to the threads waiting on the locked object. if you don't use Notify ,then certainly when it finishes it releases lock.
So that is equivalent to notify
no it's not..Consider the situation below.
class Job extends Thread {
private Integer number = 0;
public void run() {
synchronized(this) {
for (int i = 1; i < 1000000; i++) {
number++;
}
notify(); //releases lock here and your main thread continues
do sumthing...
do sumthing...
}
}
public Integer getNumber() {
return number;
}
}
if you don't use notify() ...lock will be released only after you do all your sumthings..
来源:https://stackoverflow.com/questions/11609501/is-a-notify-signalled-on-thread-finish-why-does-this-code-sample-work