0

From jdk 1.7.0_45 The instance method of Thread.join(long miilliseconds) works by making the caller Thread wait on this Thread's Object monitor.Also,the javadoc explicitly states that

As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.

  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;
                }
                wai t(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }

I don't see notifyAll() getting called so that the Thread calling join() gets the monitor for this Thread's Object

If I am calling t.join(0) on thread t,then I am not implementing notifyAll() in my run() code.So how does the caller thread(the thread which calls t.join() gets notified)

Kumar Abhinav
  • 6,565
  • 2
  • 24
  • 35

2 Answers2

4

The API documentation says (my emphasis):

Waits at most millis milliseconds for this thread to die. A timeout of 0 means to wait forever.

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.

The join method is not responsible for the notification, it's the thing doing the waiting.

The notifying would be done by whatever JVM code is responsible for terminating the thread.

Community
  • 1
  • 1
Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
  • I am not implementing notifyAll in the run() code of the joined thread t.Check my edit now – Kumar Abhinav Sep 04 '14 at 18:33
  • @Kumar: i think my answer is the same, when the thread dies the jvm fires off its notification. it's in the jdk implementation, in native code. – Nathan Hughes Sep 04 '14 at 18:38
  • so you are telling me that all threads after dying relinquish any Objects that they may have synchronized upon? – Kumar Abhinav Sep 04 '14 at 18:42
  • @Kumar: not sure i follow. the thread is the thing being synced on. the thread reaches the end of the run method it's executing, the JVM acquires the thread's lock and does a notifyAll, then it would release the lock and the thread gets sent to GC. – Nathan Hughes Sep 04 '14 at 18:48
  • I doubt "Thread gets sent to GC"..As I am having the reference of Thread Object from the main program – Kumar Abhinav Sep 04 '14 at 18:52
  • @Kumar: you're right, GC would wait til you cut it loose – Nathan Hughes Sep 04 '14 at 18:55
  • 2
    @KumarAbhinav your run() method is _not_ the base of the thread's call stack. your run() method is called by a library routine that does the notifyAll() after your run() method returns. – Solomon Slow Sep 04 '14 at 20:21
  • @jameslarge if you post this as an answer with some link,I will accept it – Kumar Abhinav Sep 04 '14 at 20:51
1

You must first understand the notify-wait mechanism. One thread waits (on an object) until another notifies it.

Example code

// in main thread
Thread t1 = new Thread(..);
t1.start();
t1.join();

The implementation of Thread#start() is native. The implementation is required to invoke notifyAll() once the Thread#run() method completes whether abruptly or normally.

This is required so that the thread calling join() can be notified.

In the example above, when the main thread calls join(), it eventually executes

wait(delay);

which is invoked on the Thread instance referenced by t1. This will cause the main thread to block until notify or notifyAll is invoked on the same Thread object which is what the native implementation of start must do, ie. invoke this.notifyAll() (probably implemented in native code).

This is also the reason why developers absolutely should not call wait and notify on Thread instances, so as not to mess with this join implementation.

Community
  • 1
  • 1
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • You said "native implementation of start must do, ie. invoke this.notifyAll()".i think notifyall should we called after joined thread's run() has completed and run will execute only when start has completed.so where will notifyall() get called from? – Kumar Abhinav Sep 04 '14 at 19:10
  • @KumarAbhinav `start` internally calls `run()`. When `run()` completes, `start` (presumably) calls `notifyAll()`. – Sotirios Delimanolis Sep 04 '14 at 19:18