Up Top

同期排他処理 : java.lang.Object.wait(), java.lang.Object.notify(), java.lang.Object.notifyAll() の処理


概要(Summary)

java.lang.Object.wait() メソッド, java.lang.Object.notify() メソッド, 及び java.lang.Object.notifyAll() メソッドは, java.lang.Object クラスのネイティブメソッドとして実装されている. これらのメソッドを呼び出すとそれぞれ以下の CVMI 関数が呼び出される.

Method CVMI function
java.lang.Object.wait() JVM_MonitorWait()
java.lang.Object.notify() JVM_MonitorNotify()
java.lang.Object.notifyAll() JVM_MonitorNotifyAll()
    ((cite: jdk/src/share/native/java/lang/Object.c))
    static JNINativeMethod methods[] = {
        {"hashCode",    "()I",                    (void *)&JVM_IHashCode},
        {"wait",        "(J)V",                   (void *)&JVM_MonitorWait},
        {"notify",      "()V",                    (void *)&JVM_MonitorNotify},
        {"notifyAll",   "()V",                    (void *)&JVM_MonitorNotifyAll},
        {"clone",       "()Ljava/lang/Object;",   (void *)&JVM_Clone},
    };

なお, wait() 処理が必要とする「待機しているスレッドの管理」用のデータ構造は inflated 状態にしか存在しない. このため, wait()/notify()/notifyAll() が呼び出された場合, ロック状態は強制的に inflated 状態になる.

より具体的にいうと, wait()/notify() の待ちキューは ObjectMonitor オブジェクトの _WaitSet フィールドで管理している. _WaitSet は ObjectWaiter オブジェクトで構成された doubly linked list であり, 以下のように使用される (See: ObjectMonitor).

なお, 現状では notify() と notifyAll() の実装は非常に似ている. 違いは, notify() は _WaitSet から 1つスレッドを選んで移動させるが, notifyAll() は _WaitSet 中の全スレッドを移動させるという点だけ.

また, wait()/notify()/notifyAll() では, timeout や interrupt による起床と, 実際に notify されたことによる起床を区別するために ObjectWaiter オブジェクトの _notified というフィールドを使っている. このフィールドは ObjectWaiter オブジェクトが生成された直後は 0 だが, ObjectMonitor::notify() で起こされると 1 になる (つまり, 起床した際に _notified がゼロのままなら notify() 以外の原因による起床) (See: ObjectWaiter).

備考(Notes)

正確には, java.lang.Object.wait() はオーバーロードされており 3つのバージョンが存在する.

ネイティブメソッドとして定義されているのは java.lang.Object.wait(long timeout). その他の 2つ (java.lang.Object.wait(), java.lang.Object.wait(long timeout, int nanos)) はそのラッパーになっている.

処理の流れ (概要)(Execution Flows : Summary)

java.lang.Object.wait(long timeout) の処理の流れ

JVM_MonitorWait()
-> ObjectSynchronizer::wait()
   -> BiasedLocking::revoke_and_rebias()
   -> ObjectSynchronizer::inflate()
   -> ObjectMonitor::wait()
      -> CHECK_OWNER()
      -> ObjectMonitor::AddWaiter()
      -> ObjectMonitor::exit()
         -> (See: here for details)
      -> os::PlatformEvent::park()  or  os::PlatformEvent::park(jlong millis)
         -> (See: here for details)
      -> ObjectMonitor::DequeueSpecificWaiter()
      -> ObjectMonitor::enter()  or  ObjectMonitor::ReenterI()
         -> (See: here for details)

java.lang.Object.wait() 及び java.lang.Object.wait(long timeout, int nanos) の処理の流れ

java.lang.Object.wait()
-> java.lang.Object.wait(long timeout)
   -> (上述)

java.lang.Object.wait(long timeout, int nanos)
-> java.lang.Object.wait(long timeout)
   -> (上述)

java.lang.Object.notify() の処理の流れ

JVM_MonitorNotify()
-> ObjectSynchronizer::notify()
   -> ObjectMonitor::notify()
      -> CHECK_OWNER()
      -> ObjectMonitor::DequeueWaiter()

java.lang.Object.notifyAll() の処理の流れ

JVM_MonitorNotifyAll()
-> ObjectSynchronizer::notifyall()
   -> ObjectMonitor::notifyAll()
      -> CHECK_OWNER()
      -> ObjectMonitor::DequeueWaiter()

処理の流れ (詳細)(Execution Flows : Details)

java.lang.Object.wait()

See: here for details

java.lang.Object.wait(long timeout, int nanos)

See: here for details

JVM_MonitorWait()

See: here for details

ObjectSynchronizer::wait()

See: here for details

ObjectMonitor::wait()

See: here for details

CHECK_OWNER()

See: here for details

ObjectMonitor::AddWaiter()

See: here for details

ObjectMonitor::DequeueSpecificWaiter()

See: here for details

ObjectMonitor::ReenterI()

See: here for details

ObjectWaiter::wait_reenter_end()

See: here for details

JVM_MonitorNotify()

See: here for details

ObjectSynchronizer::notify()

See: here for details

ObjectMonitor::notify()

See: here for details

ObjectMonitor::DequeueWaiter()

See: here for details

ObjectWaiter::wait_reenter_begin()

See: here for details

JVM_MonitorNotifyAll()

See: here for details

ObjectSynchronizer::notifyall()

See: here for details

ObjectMonitor::notifyAll()

See: here for details


This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.