кой и кога уведомява thread.wait(), когато се извика thread.join()?

thread.join() ще извика thread.wait(), но кой и кога уведомява (с thread.notify() или notifyAll()) thread.wait()?

Както знаем, присъединяването към нишката ще изчака нишката да бъде завършена, но кой извиква уведомяването за нея?


person jiafu    schedule 26.03.2012    source източник


Отговори (2)


Редактиране:

О, вие говорите за вътрешността на самия обект Thread. Вътре в join() виждаме wait(). Нещо като:

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

notify() за това се обработва от подсистемата Thread. Когато методът run() завърши, notify() се извиква на обекта Thread. Не съм сигурен дали кодът, който всъщност извиква notify(), може да се види -- изглежда, че се прави в собствен код.


Никой потребителски код не трябва да извиква notify() на този Thread обект. Кодът на Java Thread обработва това вътрешно. След като нишката приключи, извикването join() ще се върне.

Например, следният код ще се изпълни добре и извикването join() ще се върне добре без никакви wait() или notify() извиквания.

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

Важно е да се отбележи, че вероятно не трябва да се разчита на това поведение. Извикването notify() е вътрешно за нишковата система. Трябва да използвате join(), ако чакате нишката да приключи.

person Gray    schedule 26.03.2012
comment
3ks, но можете да погледнете изходния код на thread.class или да го дебъгвате с fastdebug jdk, можете да намерите, когато извикате join, ще изчакате в wait(). Така че мисля, че грешите в този момент. Но моят въпрос е кой го уведомява, когато чака в метода за присъединяване. - person jiafu; 26.03.2012
comment
@jiafu Редактирах отговора си. notify() се извиква от подсистемата Thread. Не съм сигурен, че можете да видите този код. Може да е в родна земя. - person Gray; 26.03.2012
comment
Благодаря за вашата актуализация. Както споменахте: Когато методът run() завърши, notify() се извиква на обекта Thread. Това е моят очакван отговор. Но и двамата чувстваме, че не съм сигурен дали кодът, който всъщност извиква notify(), може да се види. Благодаря. ps: как знаете факта Когато методът run() завърши, notify() се извиква на обекта Thread. Не мога да намеря никакъв документ в интернет, свързан с тази гледна точка. хаха - person jiafu; 26.03.2012
comment
@jiafu Защото така работи. Кодът е в цикъл while: while (isAlive()) { wait(0); }. Той ще извиква wait(), докато нишката вече не е жива. В края на метода run() естественият код задава alive на false и уведомява Thread. - person Gray; 26.03.2012
comment
В края на метода run() собственият код задава alive на false и уведомява сигурни ли сте? Не мога да получа fimilar с родния кодов език. Така че не мога да се уверя в това. АКО сте сигурни в това. Сигурен съм също. Много ви благодаря! - person jiafu; 26.03.2012
comment
@jiafu Така става, пич. Защо трябва да знаете това? - person Gray; 26.03.2012
comment
Интересно ми е само това. Както каза. Няма нужда да знам подробности. 3k за вашия отговор. Точно сега знам какво трябва да знам. - person jiafu; 26.03.2012
comment
@Jiafu има една поговорка, Изборът не е счупен. Много рядко има нужда да се проверява дали основна част от компютърния език функционира правилно. Oracle/Sun са отговорни за модулно и регресионно тестване на JDK/JRE. Така че няма нужда да проверявате дали Thread#join действително работи. - person Tim Bender; 02.04.2012
comment
Благодаря за топлото напомняне. - person jiafu; 06.04.2012

Що се отнася до jdk7 за linux, можете да получите отговора от изходния код на 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;
}

и когато стартирате нишка в java, нишката ще бъде 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();
}

така че lock.notify_all(thread) ще уведоми всички нишки, които чакат нишката да приключи.

person DaSqy Stc    schedule 28.06.2017