これらは ParkEvent 及び SpinLock, Mux を用いて構築された Mutex 及びモニタ実装. 長い critical section にも利用できる (See: Mutex, Monitor).
内部的には, 各 Thread オブジェクトが _MutexEvent というフィールドに ParkEvent オブジェクトを保持している. これが Mutex や Monitor の処理 (lock/unlock, wait/notify/notifyAll) で使用される.
Monitor の lock 処理では, 各スレッドが自分の _MutexEvent を Monitor に登録してから, その _MutexEvent に対して park() を呼んで待機する.
逆に unlock 処理では, 登録されている ParkEvent オブジェクトの中から 1つを選んで unpark() させることで, 寝ているスレッドを起床させる.
wait 処理では
なお, wait/notify/notifyAll では, spurious wake-up を防ぐために ParkEvent オブジェクトの Notified というフィールドを使っている.
Monitor::IWait() で寝る前に Notified をゼロにしておき, Monitor::notify() で起こした対象の Notified を 1 にする. 起きたスレッドは, Notified がゼロのままなら再び眠りにつく.
Monitor::lock() -> Monitor::TryFast() (成功すれば, ここでリターン) -> Monitor::TrySpin() (成功すれば, ここでリターン) -> Monitor::TryLock() (成功すれば, ここでリターン) -> 適当な回数だけ CAS によるロックを試みる. -> CASPTR() マクロ -> SpinPause() で時間をつぶす -> MarsagliaXORV() 又は Stall() で時間をつぶす -> Monitor::ILock() -> Monitor::TryFast() (成功すれば, ここでリターン) -> Monitor::TrySpin() (成功すれば, ここでリターン) -> Monitor::AcquireOrPush() (成功すれば, ここでリターン) (失敗した場合は, 待ち行列に追加される) -> ParkCommon() で待機する. この中では以下のどちらかを呼び出す * タイムアウト時間が指定されていない場合 -> os::PlatformEvent::park() * タイムアウト時間が指定されている場合 -> os::PlatformEvent::park(jlong millis) -> Monitor::TrySpin()
Monitor::unlock() -> Monitor::IUnlock()
Monitor::wait() -> Monitor::IWait() -> カレントスレッドを _WaitSet に登録する -> Monitor::IUnlock() -> ParkCommon() -> Monitor::ILock()
Monitor::notify() -> _WaitSet の先頭のスレッドを cxq に移動させる (これで Monitor::notify() を呼んだスレッドが unlock した際 (あるいはそれ以降の unlock() 時) に unpark() されるようになる)
Monitor::notify_all() -> Monitor::notify() (← wait しているスレッド数分だけ呼び出す) -> (上述)
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.