8

thread.join() will call thread.wait(), but who and when notifies (either with thread.notify() or notifyAll()) the thread.wait()?

As we know, thread join will wait for the thread to be completed, but who calls notify on it?

Gray
  • 115,027
  • 24
  • 293
  • 354
jiafu
  • 6,338
  • 12
  • 49
  • 73

2 Answers2

11

As for jdk7 for linux, you can get the answer from the source code of openjdk.

/jdk7/hotspot/src/os/linux/vm/os_linux.cpp

int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread);

static void *java_start(Thread *thread) {
  ...
  thread->run();
  return 0;
}

and when start thread in java, the thread will be instanceof JavaThread.

/jdk7/hotspot/src/share/vm/runtime/thread.cpp

void JavaThread::run() {
  ...
  thread_main_inner();
}

void JavaThread::thread_main_inner() {
  ...
  this->exit(false);
  delete this;
}

void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
  ...
  // Notify waiters on thread object. This has to be done after exit() is called
  // on the thread (if the thread is the last thread in a daemon ThreadGroup the
  // group should have the destroyed bit set before waiters are notified).
  ensure_join(this);
  ...
}

static void ensure_join(JavaThread* thread) {
  // We do not need to grap the Threads_lock, since we are operating on ourself.
  Handle threadObj(thread, thread->threadObj());
  assert(threadObj.not_null(), "java thread object must exist");
  ObjectLocker lock(threadObj, thread);
  // Ignore pending exception (ThreadDeath), since we are exiting anyway
  thread->clear_pending_exception();
  // Thread is exiting. So set thread_status field in  java.lang.Thread class to TERMINATED.
  java_lang_Thread::set_thread_status(threadObj(), java_lang_Thread::TERMINATED);
  // Clear the native thread instance - this makes isAlive return false and allows the join()
  // to complete once we've done the notify_all below
  java_lang_Thread::set_thread(threadObj(), NULL);
  lock.notify_all(thread);
  // Ignore pending exception (ThreadDeath), since we are exiting anyway
  thread->clear_pending_exception();
}

so lock.notify_all(thread) will notify all threads whose wait for the thread to finish.

SDJSK
  • 1,292
  • 17
  • 24
8

Edit:

Oh, you are talking about inside of the Thread object itself. Inside of join() we do see a wait(). Something like:

while (isAlive()) {
    wait(0);
}

The notify() for this is handled by the Thread subsystem. When the run() method finishes, the notify() is called on the Thread object. I'm not sure if the code that actually calls notify() can be seen -- it seems to be done in native code.


No user code needs to call notify() on that Thread object. The Java Thread code handles this internally. Once the thread finishes, the join() call will return.

For example, the following code will execute fine and the join() call will return fine without any wait() or notify() calls.

Thread thread = new Thread(new Runnable() {
   public void run() {
      // no-op, just return immediately
   }
});
thread.start();
thread.join();

It is important to note that this behavior should probably not be relied upon. The notify() call is internal to the thread system. You should use join() if you are waiting for a thread to finish.

Gray
  • 115,027
  • 24
  • 293
  • 354
  • 3ks, But you can take a look at thread.class source code or debug it with fastdebug jdk, you can find when you call join, you will wait at wait(). So I think you are wrong at this point. But my quesiton is that who notify it when waiting inside join method. – jiafu Mar 26 '12 at 03:24
  • @jiafu I've edited my answer. The `notify()` is called from within the `Thread` subsystem. I'm not sure you can see that code. It may be in native land. – Gray Mar 26 '12 at 03:34
  • Thanks for your update. As you mentioned:"When the run() method finishes, the notify() is called on the Thread object." That is my expected answer. But We both feel that "I'm not sure if the code that actually calls notify() can be seen". Thanks. ps: how you know the fact "When the run() method finishes, the notify() is called on the Thread object". I can't find any document in internet related with this viewpoint. haha – jiafu Mar 26 '12 at 04:21
  • @jiafu Because that's how it works. The code is in a while loop: `while (isAlive()) { wait(0); }`. It will call `wait()` until the thread is no longer alive. At the end of the `run()` method the native code sets alive to false and notifies the `Thread`. – Gray Mar 26 '12 at 04:25
  • "At the end of the run() method the native code sets alive to false and notifies the " are you sure ? I can't get fimilar with native code language. So I can't make sure this. IF you sure of it. I sure it too. Many thank to you ! – jiafu Mar 26 '12 at 04:29
  • @jiafu That's how it works dude. Why do you need to know this? – Gray Mar 26 '12 at 04:38
  • I am only interesting it. As you said. I has no need to know detail. 3ks for your reply . Just now, I know what I should know. – jiafu Mar 26 '12 at 04:49
  • @Jiafu there is a saying, "Select is not broken". Very rarely is there ever the need to verify that a core part of a computer language functions correctly. Oracle/Sun are responsible for unit and regression testing the JDK/JRE. So there is no need to verify that `Thread#join` does in fact work. – Tim Bender Apr 02 '12 at 16:24
  • Thanks for your warm remider. – jiafu Apr 06 '12 at 02:31