Is a notify signalled on thread finish? Why does this code sample work?

落花浮王杯 提交于 2019-12-06 17:29:12

问题


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?


回答1:


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?




回答2:


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.




回答3:


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.




回答4:


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.




回答5:


A thread object is automatically notified when the thread finishes, that's why the main thread doesn't get stuck.




回答6:


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!