破除java神話之五:等待的線程是按照優先順序順序被喚醒的

來源:互聯網
上載者:User
在編寫多線程代碼的時候經常發生多個線程等待一個事件的情況。這種情況多發生於多個線程在同步方法或者同步塊內調用wait方法等待同一個被鎖住的對象。當另一個鎖住該對象的線程從同步方法或者同步塊中調用notify或者notifyAll方法時這些等待線程被喚醒。notify調用僅僅喚醒一個線程,因此如果有多個線程正處於等待狀態,那麼不會有對鎖的競爭。另一方面,notifyAll調用喚醒所有的等待線程而造成競爭,然而只有一個線程能夠得到鎖,其它的都會被阻塞。
當多個線程處於等待狀態時的問題是當調用notify或者notifyAll方法後哪一個線程將運行?很多程式員不正確的假定存在一種預定義的順序表明線程如何被喚醒。一些認為是高優先順序的線程首先被喚醒,另一些可能認為是等待了最長時間的線程首先被喚醒。不幸的是上面的假設都是不對的。在這些情況下,哪個線程被喚醒是不確定的,也許是最高優先順序的線程,也許是等待最長的線程,但是沒有保證。
線程的優先順序不能決定它是否被喚醒(在使用notify方法的情況下)或者在多線程環境下的喚醒順序(在使用notifyAll方法的情況下)。因此,因此你永遠不應該假設線程的喚醒順序。另外,你也永遠不應該對搶佔過程中的線程調度做任何假設。線程調度是實現相關的(implementation-dependent),不同的平台的調度機制是不同的。如果你想你的程式具有可移植性就不應該做這樣的不明智的假設。
另外,notifyAll和notify方法沒有提供喚醒等待進程的確定順序,具體的順序是依賴JVM的,並且notifyAll所能保證的事情不超過喚醒所有的等待線程。這個狀況使得當你想以某種特定的順序喚醒多個線程時會出現問題。
有兩種辦法達到控制線程的喚醒順序:

1、使用精確喚醒模式(
Specific notification pattern)
2、使用實現了即時規範的JVM(RTSJ,Real-Time Specification for Java)(譯者註:這其實不應該算一種好的方法,這加大了對特定JVM的依賴,打破了可移植性)

精確喚醒模式由Tom Cargill開發,詳細說明了如何控制調用notify和notifyAll時的線程的喚醒順序。這個實現是通過對需要被一起喚醒的每個線程或者每一套線程設定一個單獨的鎖達到的。通過對特定的鎖進行釋放而達到可定義的通知順序。
如果實現合適,那麼這種模式的執行代價是最小的。然而不可避免的要增加編碼的複雜性,但是這個複雜性可以通過你得到的控制性抵消掉,如果你需要這樣的控制,你可以考慮實現這個模式。

RTSJ改變了某些java語義的標準行為。其中之一就是確保等待線程按照優先順序排序。因此當多個線程處於等待狀態而調用了notify或者notifyAll,那麼具有最高優先順序的那個將首先執行,其它的繼續等待。
通常,這不是推薦的做法,除非是進行即時編程。已經有幾種不同的折衷方案使得java可以進行即時編程。建立RTSJ的最重要的一個原則就是及時性比執行速度更重要!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.