C# 4.0 “修複了”死結問題

來源:互聯網
上載者:User

幾年前,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所說的“終止異常純粹就是找死”。

查看英文原文:C# 4.0 "Fixes" Deadlock Issue

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.