[英]Why are wait() and notify() declared in Java's Object class?
為什么在Object
類中聲明了wait()
和notify()
方法,而不是Thread
類?
因為,您在給定的Object(或特別是其監視器)上等待使用此功能。
我想你可能會誤解這些方法是如何工作的。 它們不僅僅處於線程粒度級別,即它不是僅調用wait()
並且在下一次調用notify()
被喚醒的情況。 相反,您始終對特定對象調用wait()
,並且只會通過對該對象進行notify
的調用來喚醒。
這很好,因為否則並發原語就不會擴展; 它等同於具有全局命名空間,因為在程序中的任何地方調用notify()
都有可能弄亂任何並發代碼,因為它們會喚醒在wait()
調用上阻塞的任何線程。 因此你在特定對象上調用它們的原因; 它為wait-notify對提供了一個上下文,因此當你在私有對象上調用myBlockingObject.notify()
,你可以確定你只會喚醒在你的類中調用wait方法的線程。 一些可能在另一個對象上等待的Spring線程將不會被此調用喚醒,反之亦然。
編輯:或者從另一個角度解決它 - 我希望你的問題,你認為你會得到一個等待線程的句柄,並在該線程上調用notify()
來喚醒它。 它沒有這樣做的原因是你必須自己做很多家務。 要等待的線程必須在其他線程可以看到的地方發布對自己的引用; 這必須正確同步以強制一致性和可見性。 當你想要喚醒一個線程時,你必須抓住這個引用,喚醒它,並從你讀取它的任何地方刪除它。 還有很多更多的手動腳手架參與,並與剛剛調用的腳麻它(尤其是在並發環境中)有很多更多的機會myObj.wait()
在休眠線程,然后myObj.notify()
在waker的線程。
最簡單明了的原因是任何Object(不僅僅是一個線程)都可以作為線程的監視器。 在監視器上調用wait和notify。 正在運行的線程檢查監視器。 所以wait和notify方法是在Object而不是Thread
因為一次只有一個線程可以擁有對象的監視器,並且此監視器是線程正在等待或通知的內容。 如果您閱讀了Object.notify()
和Object.wait()
的javadoc , Object.notify()
詳細介紹它。
同步機制涉及一個概念 - 對象的監視。 調用wait()時,將請求監視器並暫停執行,直到獲取監視器或發生InterruptedException。 調用notify()時,將釋放監視器。
如果將wait()和notify()放在Thread類而不是Object類中,那么我們來看一個場景。 在代碼中的某一點,調用currentThread.wait()
,然后訪問對象anObject
。
//.........
currentThread.wait();
anObject.setValue(1);
//.........
當調用currentThread.wait()時,將請求監視currentThread
,並且在獲取監視器或發生InterruptedException之前不再執行任何操作。 現在處於等待狀態時,如果從另一個線程調用駐留在currentThread
的另一個對象anotherObject
的方法foo()
,即使被調用的方法foo()
不訪問anObject
,它也會被卡住。 如果在anObject
調用第一個wait()方法而不是線程本身,則駐留在同一線程中的對象上的其他方法調用(不訪問anObject
)不會被卡住。
因此,在Object類(或其子類)上調用wait()和notify()方法可以提供更高的並發性,這就是為什么這些方法在Object類中,而不是在Thread類中。
其他一些答案使用“監視器”一詞,但沒有一個解釋它的含義。
名稱“monitor”是在20世紀70年代創造的,它引用了一個具有自己的內部鎖定和相關的等待/通知機制的對象。 https://en.wikipedia.org/wiki/Monitor_%28synchronization%29
二十年后,台式機,多處理器計算機出現了新的短暫時刻,認為為他們設計軟件的正確方法是創建面向對象的程序,其中每個對象都是監控。
事實證明這並不是一個有用的想法,但這個短暫的時刻恰好恰好是Java編程語言的發明時期。
請閱讀此處以獲取等待和通知的說明。
最好在應用程序中避免使用這些並使用較新的java.util.concurrent包。
我將以簡單的方式說:
要調用wait()或notify(),您需要擁有對象監視器 - 這意味着wait()或notify()需要出現在synchronized塊中
synchronized(monitorObj){
monitorObj.wait() or even notify
}
這就是這些方法存在於對象類中的原因
這是因為,這些方法用於線程間通信,並且通過使用鎖來進行interthread通信,但是鎖與對象相關聯。因此它在對象類中。
Wait和Notify方法用於Java中兩個Thread之間的通信。 所以Object類是正確的位置,使它們可用於Java中的每個對象。
另一個原因是鎖定是基於每個對象提供的。 線程需要鎖定並等待鎖定,他們不知道哪些線程持有鎖而不知道鎖定是否被某個線程保持並且他們應該等待鎖定而不是知道哪個線程在同步塊內並要求它們釋放鎖
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.