posts - 241,  comments - 116,  trackbacks - 0

          幾年前,Eric Lippert注意到根據同樣源代碼進行優化構建和非優化構建會導致不同的潛在死鎖。這個問題會在C# 4.0中被“修復”。“修復”放在引號當中,是因為解決方式也有它自己的問題。

          最初的問題可能來自于編譯器在把IL轉化為機器代碼的時候,根據你是否打開或關閉優化器和調試器,以非一致的行為插入了no-op指令。Lippert提道:

          回想一下,lock(obj){body}實際上就是下面代碼的語法:

          var temp = obj;
          Monitor.Enter(temp);
          try { body }
          finally { Monitor.Exit(temp); }

          這里的問題是,如果編譯器在Monitor.Enter和受try保護的區域之間生成了no-op指令,那么運行時就有可能 在Monitor.Enter之后和try之前拋出線程終止異常。在這樣的情形下,finally不會執行,那么也就產生了程序鎖泄漏,程序有可能出現死 鎖。如果在非優化和優化構建中不存在差異,就不存在這個問題。


          不過。這個解決方案[譯注:C# 4.0是將Monitor.Enter()移入到try子句中,并在Enter的時候會傳遞一個引用值,標識鎖是否被占用。在finnally子句中,會 首先判斷鎖是否被占用,如果被占用,則釋放鎖。]也有它自己的問題。據Eric說,“保持一致與不一致相比,完全就是五十步笑百步。它仍然存在很大的問 題...這樣生成的代碼所[譯注:生成的代碼是指編譯器將lock轉換為IL,實際上就相當于使用Monitor的語法]隱含的意義就是認為死鎖程序是可 能 發生的最糟糕的事情。這種說法未必準確。”

          鎖的目的是為了保護可變資源,或者換句話說,是為了避免可變資源的多個潛在用戶訪問資源已被破壞的版本。4.0版本的現有解決方案并沒有包含回滾到 原始狀態的功能,也沒有保證可變資源的完整性。強行進入lock語句的finally子句、釋放鎖以及允許訪問任意等待 線程(該線程占用了已被破壞的資源),都有可能引發異常。這一解決方案在結果的一致性、降低死鎖的可能性和對訪問被破壞狀態可能付出的代價方面,做出了折 衷。該問題尤其在多線程編程中會存在風險。

          這個特定的折衷是對兩種糟糕結果的選擇:程序死鎖,還是不再保護重要資源的狀態。所謂“兩害相權取其輕”,當我們進行多線程編程時,就必須在多個設計決策與權衡中做出一個選擇。

          這篇文章反響熱烈, 一些開發人員認為這類設計問題不只限于多線程,在“安全鎖”和“安全異常”之間也存在不同之處。Lippert也同意多線程只會讓難處理的問題更難,“正 確獲得鎖僅僅是萬里長征的第一步”,你的設計還需要考慮其他各種異常,以及在異常發生后如何處理它們。大量的回復者指出終止線程的危險性,并部分同意 Lippert所說的“終止異常純粹就是找死”。

          posted on 2009-03-24 17:14 墻頭草 閱讀(230) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          人人游戲網 軟件開發網 貨運專家
          主站蜘蛛池模板: 慈溪市| 丰台区| 姜堰市| 积石山| 百色市| 泽库县| 内丘县| 介休市| 龙井市| 文登市| 富锦市| 垣曲县| 霍城县| 建始县| 奈曼旗| 南川市| 连云港市| 当雄县| 霍山县| 屏边| 茶陵县| 肃南| 常熟市| 华容县| 稻城县| 武威市| 禄劝| 衡东县| 平武县| 宜良县| 名山县| 武威市| 托里县| 南郑县| 洛川县| 高州市| 永兴县| 开化县| 佛坪县| 长宁县| 周宁县|