熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java高級技術 >> 正文

破除Java神話之線程按優先級喚醒

2013-11-23 19:56:01  來源: Java高級技術 

    在編寫多線程代碼的時候經常發生多個線程等待一個事件的情況這種情況多發生於多個線程在同步方法或者同步塊內調用wait方法等待同一個被鎖住的對象當另一個鎖住該對象的線程從同步方法或者同步塊中調用notify或者notifyAll方法時這些等待線程被喚醒notify調用僅僅喚醒一個線程因此如果有多個線程正處於等待狀態那麼不會有對鎖的競爭另一方面notifyAll調用喚醒所有的等待線程而造成競爭然而只有一個線程能夠得到鎖其它的都會被阻塞

    當多個線程處於等待狀態時的問題是當調用notify或者notifyAll方法後哪一個線程將運行?很多程序員不正確的假定存在一種預定義的順序表明線程如何被喚醒一些認為是高優先級的線程首先被喚醒另一些可能認為是等待了最長時間的線程首先被喚醒不幸的是上面的假設都是不對的在這些情況下哪個線程被喚醒是不確定的也許是最高優先級的線程也許是等待最長的線程但是沒有保證

    線程的優先級不能決定它是否被喚醒(在使用notify方法的情況下)或者在多線程環境下的喚醒順序(在使用notifyAll方法的情況下)因此因此你永遠不應該假設線程的喚醒順序另外你也永遠不應該對搶占過程中的線程調度做任何假設線程調度是實現相關的(implementationdependent)不同的平台的調度機制是不同的如果你想你的程序具有可移植性就不應該做這樣的不明智的假設

    另外notifyAll和notify方法沒有提供喚醒等待進程的確定順序具體的順序是依賴JVM的並且notifyAll所能保證的事情不超過喚醒所有的等待線程這個狀況使得當你想以某種特定的順序喚醒多個線程時會出現問題

    有兩種辦法達到控制線程的喚醒順序

    使用精確喚醒模式

    (Specific notification pattern)

    使用實現了實時規范的JVM(RTSJRealTime Specification for Java)(譯者注這其實不應該算一種好的方法這加大了對特定JVM的依賴打破了可移植性)

    精確喚醒模式由Tom Cargill開發詳細說明了如何控制調用notify和notifyAll時的線程的喚醒順序這個實現是通過對需要被一起喚醒的每個線程或者每一套線程設置一個單獨的鎖達到的通過對特定的鎖進行釋放而達到可定義的通知順序

    如果實現合適那麼這種模式的執行代價是最小的然而不可避免的要增加編碼的復雜性但是這個復雜性可以通過你得到的控制性抵消掉如果你需要這樣的控制你可以考慮實現這個模式

    RTSJ改變了某些java語義的標准行為其中之一就是確保等待線程按照優先級排序因此當多個線程處於等待狀態而調用了notify或者notifyAll那麼具有最高優先級的那個將首先執行其它的繼續等待

    通常這不是推薦的做法除非是進行實時編程已經有幾種不同的折衷方案使得java可以進行實時編程創建RTSJ的最重要的一個原則就是及時性比執行速度更重要!


From:http://tw.wingwit.com/Article/program/Java/gj/201311/27687.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.