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

Java線程模型缺陷研究[4]

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

    設想一個線程調用a() 但在獲得  lock 之後在獲得 lock 之前被剝奪運行權 第二個線程進入運行調用 b() 獲得了 lock 但是由於第一個線程占用 lock 所以它無法獲得 lock 所以它隨後處於等待狀態此時第一個線程被喚醒它試圖獲得 lock 但是由於被第二個線程占據所以無法獲得此時出現死鎖

    編譯器(或虛擬機)會重新排列請求鎖的順序使lock 總是被首先獲得這就消除了死鎖

    但是這種方法對多線程不一定總成功所以得提供一些方法來自動打破死鎖一個簡單的辦法就是在等待第二個鎖時常釋放已獲得的鎖

    如果等待鎖的每個程序使用不同的超時值就可打破死鎖而其中一個線程就可運行我建議用以下的語法來取代前面的代碼

    synchronized語句將永遠等待但是它時常會放棄已獲得的鎖以打破潛在的死鎖可能在理想情況下每個重復等待的超時值比前一個相差一隨機值

    改進wait() 和 notify()

    wait()/ notify() 系統也有一些問題 無法檢測 wait() 是正常返回還是因超時返回 無法使用傳統條件變量來實現處於一個信號(signaled)狀態 太容易發生嵌套的監控(monitor)鎖定

    超時檢測問題可以通過重新定義wait() 使它返回一個 boolean 變量 (而不是 void ) 來解決一個 true 返回值指示一個正常返回而 false 指示因超時返回

    基於狀態的條件變量的概念是很重要的如果此變量被設置成false 狀態那麼等待的線程將要被阻斷直到此變量進入 true 狀態任何等待 true 的條件變量的等待線程會被自動釋放 (在這種情況下 wait() 調用不會發生阻斷

    嵌套監控鎖定問題非常麻煩我並沒有簡單的解決辦法嵌套監控鎖定是一種死鎖形式當某個鎖的占有線程在掛起其自身之前不釋放鎖時會發生這種嵌套監控封鎖

    此例中在get() 和 put() 操作中涉及兩個鎖一個在 Stack 對象上另一個在 LinkedList 對象上下面我們考慮當一個線程試圖調用一個空棧的 pop() 操作時的情況此線程獲得這兩個鎖然後調用 wait() 釋放 Stack 對象上 的鎖但是沒有釋放在 list 上的鎖如果此時第二個線程試圖向堆棧中壓入一個對象它會在 synchronized(list) 語句上永遠掛起而且永遠不會被允許壓入一個對象由於第一個線程等待的是一個非空棧這樣就會發生死鎖這就是說第一個線程永遠無法從 wait() 返回因為由於它占據著鎖而導致第二個線程永遠無法運行到 notify() 語句

    在這個例子中有很多明顯的辦法來解決問題例如對任何的方法都使用同步但是在真實世界中解決方法通常不是這麼簡單

    一個可行的方法是在wait() 中按照反順序釋放當前線程獲取的 所有 鎖然後當等待條件滿足後重新按原始獲取順序取得它們但是我能想象出利用這種方式的代碼對於人們來說簡直無法理解所以我認為它不是一個真正可行的方法如果您有好的方法請給我發 email

    我也希望能等到下述復雜條件被實現的一天例如

    其中a b 和 c 是任意對象

    修改Thread 類

    同時支持搶占式和協作式線程的能力在某些服務器應用程序中是基本要求尤其是在想使系統達到最高性能的情況下我認為 Java 編程語言在簡化線程模型上走得太遠了並且 Java 編程語言應支持 Posix/Solaris 的綠色(green)線程輕便(lightweight)進程概念(在(Taming Java Threads 第一章中討論) 這就是說有些 Java 虛擬機的實現(例如在 NT 上的 Java 虛擬機)應在其內部仿真協作式進程其它 Java 虛擬機應仿真搶占式線程而且向 Java 虛擬機加入這些擴展是很容易的

    一個 Java 的Thread 應始終是搶占式的這就是說一個 Java 編程語言的線程應像 Solaris 的輕便進程一樣工作 Runnable 接口可以用於定義一個 Solaris 式的綠色線程此線程必需能把控制權轉給運行在相同輕便進程中的其它綠色線程

    能有效地為Runnable 對象產生一個綠色線程並把它綁定到由 Thread 對象代表的輕便進程中這種實現對於現有代碼是透明的因為它的有效性和現有的完全一樣

    把Runnable 對象想成為綠色線程使用這種方法只需向 Thread 的構造函數傳遞幾個 Runnable 對象就可以擴展 Java 編程語言的現有語法以支持在一個單一輕便線程有多個綠色線程(綠色線程之間可以相互協作但是它們可被運行在其它輕便進程 ( Thread 對象) 上的綠色進程( Runnable 對象) 搶占例如下面的代碼會為每個 runnable 對象創建一個綠色線程這些綠色線程會共享由 Thread 對象代表的輕便進程

[]  []  []  []  []  []  []  


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