破除java神話之執行緒按優先順序喚醒
破除java神話之執行緒按優先順序喚醒[@more@] 在編寫多執行緒程式碼的時候經常發生多個執行緒等待一個事件的情況。這種情況多發生於多個執行緒在同步方法或者同步塊內呼叫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的最重要的一個原則就是及時性比執行速度更重要!
當多個執行緒處於等待狀態時的問題是當呼叫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的最重要的一個原則就是及時性比執行速度更重要!
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10901326/viewspace-965626/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Java之執行緒的優先順序Java執行緒
- java執行緒優先順序Java執行緒
- Swift多執行緒之Operation:按優先順序載入圖片Swift執行緒
- 警惕執行緒的優先順序執行緒
- Java 多執行緒基礎(十一)執行緒優先順序和守護執行緒Java執行緒
- 【java】【多執行緒】睡眠/守護/加入/禮讓執行緒,執行緒優先順序(4)Java執行緒
- 從Java到JVM到OS執行緒的優先順序JavaJVM執行緒
- 多優先順序執行緒池實踐執行緒
- java基礎:執行緒方法之設定優先順序Java執行緒
- linux/unix中設定執行緒優先順序Linux執行緒
- Java 多執行緒基礎(六)執行緒等待與喚醒Java執行緒
- 多執行緒-執行緒排程及獲取和設定執行緒優先順序執行緒
- Python3 執行緒優先順序佇列( Queue)Python執行緒佇列
- 多執行緒——虛假喚醒執行緒
- 程式設計思想之多執行緒與多程式(2):執行緒優先順序與執行緒安全程式設計執行緒
- Linux排程策略及執行緒優先順序設定Linux執行緒
- Python執行緒專題10:queue、多執行緒按順序執行Python執行緒
- Nachos實驗實現執行緒id、限制執行緒數和更改排程演算法(按優先順序排程)執行緒演算法
- java運算子優先順序Java
- Java中如何保證執行緒順序執行Java執行緒
- 工作執行緒的喚醒及建立(19)執行緒
- 執行緒虛假喚醒問題剖析執行緒
- java setPriority()設定優先順序Java
- CSS優先順序CSS
- 執行緒執行順序——CountDownLatch、CyclicBarrier 、join()、執行緒池執行緒CountDownLatch
- java多執行緒之消費生產模型-使用synchronized解決虛假喚醒Java執行緒模型synchronized
- 多執行緒-生產者消費者之等待喚醒機制程式碼優化執行緒優化
- 多執行緒-生產者消費者之等待喚醒機制執行緒
- unittest--TestCase 按宣告順序執行
- 中斷優先順序
- Linux c多執行緒執行順序Linux執行緒
- Java優先順序佇列DelayedWorkQueue原理分析Java佇列
- CSS之選擇器及其優先順序CSS
- python運算子及優先順序順序Python
- [java基礎] 之 表示式和運算子的優先順序Java
- kafka多執行緒順序消費Kafka執行緒
- join方法應用之一——按順序輸出三個執行緒執行緒
- java字串連線和運算子優先順序Java字串