3 回答

TA貢獻1880條經驗 獲得超4個贊
Object.wait()JVM_MonitorWait根據ThreadReferencejavadoc ,功能是使用本機方法實現的:
/** Thread is waiting - Object.wait() or JVM_MonitorWait() was called */
public final int THREAD_STATUS_WAIT = 4;
該方法的實現可以在jvm.cppand uses中找到ObjectSynchronizer::wait:
JVM_ENTRY(void, JVM_MonitorWait(JNIEnv* env, jobject handle, jlong ms))
JVMWrapper("JVM_MonitorWait");
Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
JavaThreadInObjectWaitState jtiows(thread, ms != 0);
if (JvmtiExport::should_post_monitor_wait()) {
JvmtiExport::post_monitor_wait((JavaThread *)THREAD, (oop)obj(), ms);
// The current thread already owns the monitor and it has not yet
// been added to the wait queue so the current thread cannot be
// made the successor. This means that the JVMTI_EVENT_MONITOR_WAIT
// event handler cannot accidentally consume an unpark() meant for
// the ParkEvent associated with this ObjectMonitor.
}
ObjectSynchronizer::wait(obj, ms, CHECK);
JVM_END
ObjectSynchronizer::wait實現是 insynchronizer.cpp并委托給ObjectMonitor::waitin objectMonitor.cpp。
如果您繼續深入研究,您最終將獲得依賴于平臺的本機 Java 線程實現。在 Linux 上libpthread.so,這將最終處理線程狀態的變化。

TA貢獻1853條經驗 獲得超9個贊
最簡單的形式是帶條件退出的無限循環嗎?
不,不是。這是低效的,而不是通常的做法。
細節很復雜并且取決于系統(請參閱@Karol 的代碼鏈接的答案),但一般方法如下。
當線程調用wait()
時,該方法執行以下操作:
將線程詳細信息添加到互斥對象的“等待對象”隊列中。
放棄線程的互斥鎖。
通過告訴操作系統使其進入睡眠狀態來“停放”線程。
操作系統找到一些其他線程來調度。如果沒有,它會導致核心進入低功耗“空閑”循環或暫停它或其他東西。(這取決于操作系統和硬件。)
然后當另一個線程調用時notify
, notify 方法執行以下操作:
它從互斥隊列中刪除一個線程。
它告訴操作系統應該喚醒(以前)等待的線程。
它從
notify()
調用中返回并(希望)釋放互斥鎖。
操作系統執行以下操作:
它找到一個空閑的處理器來運行線程,然后啟動。
如果沒有可用的內核,操作系統會將線程添加到調度程序的可運行線程隊列中。
當線程啟動時,它首先嘗試重新獲取互斥鎖......如果其他線程仍然持有鎖,這可能會導致它重新進入睡眠狀態。
最后
wait
調用返回,線程通常會重新檢查條件變量,然后釋放鎖。
關鍵是(通常)沒有在線程等待時消耗 CPU 的無限循環。
什么是等待請求的資源消耗最少的方式,這就是讓我問這個的原因。
Object.wait
資源消耗最少的方式是Object.notify
......

TA貢獻1858條經驗 獲得超8個贊
在同步編程中,監視器可以被假設為一個盒子,或者更具體地說是一個控制盒(用于對對象進行任何更改),在任何給定時刻只有一個線程的空間。因此,可以防止多個線程同時寫入一個對象并保護對象不被損壞。在其中,wait() 方法告訴一個線程,如果任何其他線程已經在監視器中,如果是,則告訴調用線程等待其他線程出來。或者從技術上講,告訴調用線程 SLEEP 直到收到通知。
它停止調用線程中代碼的任何進一步執行,這與無限循環不同,在無限循環中,執行繼續,但循環之后沒有代碼執行,直到循環中斷。
添加回答
舉報