posts - 241,  comments - 116,  trackbacks - 0

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

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

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

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

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


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

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

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

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

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

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


          網(wǎng)站導航:
           
          人人游戲網(wǎng) 軟件開發(fā)網(wǎng) 貨運專家
          主站蜘蛛池模板: 万年县| 济宁市| 瓮安县| 西城区| 北京市| 阿尔山市| 定结县| 马尔康县| 昭觉县| 夏邑县| 辉县市| 阜平县| 搜索| 咸宁市| 库伦旗| 临洮县| 成武县| 观塘区| 济阳县| 收藏| 江陵县| 通榆县| 德江县| 堆龙德庆县| 丽江市| 朝阳区| 阿拉善左旗| 获嘉县| 武鸣县| 沙雅县| 手游| 岳普湖县| 右玉县| 广西| 泸定县| 滨州市| 乌海市| 商洛市| 浦北县| 延吉市| 昌平区|