これらは 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.