Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

who and when notify the thread.wait() when thread.join() is called?

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?

like image 554
jiafu Avatar asked Mar 26 '12 03:03

jiafu


2 Answers

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.

like image 129
SDJSK Avatar answered Sep 28 '22 00:09

SDJSK


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.

like image 26
Gray Avatar answered Sep 28 '22 00:09

Gray