當多個線程可以調用單個對象的屬性和方法時,對這些調用進行同步處理是非常重要的。 否則,一個線程可能會中斷另一個線程正在執行的任務,使該對象處于一種無效狀態。 其成員不受這類中斷影響的類叫做線程安全類。
Common Language Infrastructure 提供了幾種可用來同步對實例和靜態成員的訪問的策略:
-
同步代碼區域。 可以使用 Monitor 類或此類的編譯器支持來僅同步需要此類的代碼塊,從而提高性能。
-
手動同步。 可以使用 .NET Framework 類庫提供的同步對象。 請參見 同步基元概述 ,這部分對 Monitor 類進行了討論。
-
同步上下文。 可以使用 SynchronizationAttribute 為 ContextBoundObject 對象啟用簡單的自動同步。
-
System.Collections.Concurrent 命名空間中的集合類。 這些類提供了內置的同步添加和移除操作。 有關更多信息,請參見 線程安全集合 。
公共語言運行時提供一個線程模型,在該模型中,類分為許多類別,這些類別可以根據要求以各種不同的方式進行同步。 下表顯示了為具有給定同步類別的字段和方法提供的同步支持。
類別
全局字段
靜態字段
靜態方法
實例字段
實例方法
特定代碼塊
無同步 |
否 |
否 |
否 |
否 |
否 |
否 |
同步上下文 |
否 |
否 |
否 |
是 |
是 |
否 |
同步代碼區域 |
否 |
否 |
僅當標記時 |
否 |
僅當標記時 |
僅當標記時 |
手動同步 |
手動 |
手動 |
手動 |
手動 |
手動 |
手動 |
可以使用 Monitor 類或編譯器關鍵字來同步代碼塊、實例方法和靜態方法。 不支持同步靜態字段。
Visual Basic 和 C# 都支持使用特定語言關鍵字標記代碼塊,在 C# 中使用的是 lock 語句,在 Visual Basic 中使用的是 SyncLock 語句。 當由線程執行該代碼時,會嘗試獲取鎖。 如果該鎖已由其他線程獲取,則在鎖變為可用狀態之前,該線程一直處于禁止狀態。 當線程退出同步代碼塊時,鎖就會被釋放,它與線程的退出方式無關。
lock 和 SyncLock 語句是使用 Monitor :: Enter 和 Monitor :: Exit 實現的,因此,可以在同步區域中將它們與 Monitor 的其他方法一起使用。 |
還可以用 MethodImplAttribute 和 MethodImplOptions.Synchronized 修飾方法,其效果和使用 Monitor 或其中一個編譯器關鍵字鎖定整個方法體相同。
Thread :: Interrupt 可用于使線程跳出阻止操作(如等待訪問同步代碼區域)。 Thread.Interrupt 還用于使線程跳出 Thread :: Sleep 等操作。
為保護 static 方法(Visual Basic 中的 Shared 方法),請不要鎖定類型,即:C# 中的 typeof(MyType) 、Visual Basic 中的 GetType(MyType) 或 C++ 中的 MyType::typeid 。 而應改用私有靜態對象。 類似地,不要使用 C# 中的 this (Visual Basic 中的 Me )鎖定實例方法。 而應使用私有對象。 類或實例可由其他代碼鎖定,您自己的代碼進行鎖定可能會引起死鎖或性能問題。 |
編譯器支持
Visual Basic 和 C# 都支持使用 Monitor :: Enter 和 Monitor :: Exit 來鎖定對象的語言關鍵字。 Visual Basic 支持 SyncLock 語句;C# 支持 lock 語句。
這兩種情況下,如果代碼塊中引發異常,則 lock 或 SyncLock 鎖獲取的鎖將自動釋放。 C# 和 Visual Basic 編譯器在發出 try / finally 塊時,在 try 的起始處使用 Monitor.Enter ,在 finally 塊中使用 Monitor.Exit 。 如果 lock 或 SyncLock 塊內部引發了異常,則會運行 finally 處理程序,從而使您可以執行任何清除工作。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
