分享方式:


同步多執行緒處理的資料

當多個執行緒可以對單一物件的屬性和方法進行呼叫時,請務必同步處理這些呼叫。 否則某個執行緒可能會中斷另一個執行緒正在執行的作業,而且物件可能會處於無效狀態。 其成員受到保護免於這種中斷的類別,稱為安全執行緒。

.NET 提供數種策略來同步存取執行個體和靜態成員:

  • 同步程式碼區域。 您可以使用 Monitor 類別或此類別的編譯器支援,僅同步處理需要它的程式碼區塊,進而改善效能。

  • 手動同步處理。 您可以使用 .NET Framework 類別庫提供的同步物件。 請參閱同步處理原始物件概觀,其中包括 Monitor 類別的討論。

  • 同步處理的內容。 針對 .NET Framework 和 Xamarin 應用程式,您可以使用 SynchronizationAttribute 來啟用 ContextBoundObject 物件的簡單自動同步。

  • System.Collections.Concurrent 命名空間中的集合類別。 這些類別會提供內建同步處理新增和移除作業。 如需詳細資訊,請參閱安全執行緒集合

通用語言執行平台提供執行緒模型,其中類別分為一些分類,可以根據需求以各種不同的方式同步處理。 下表顯示為指定同步處理分類的欄位和方法提供哪些同步處理支援。

類別 全域欄位 靜態欄位 靜態方法 執行個體欄位 執行個體方法 特定程式碼區塊
沒有同步處理 No No
同步處理的內容 No .是 .是 No
同步程式碼區域 No No 只有當標記時 No 只有當標記時 只有當標記時
手動同步處理 手動 手動 手動 手動 手動 手動

無同步

這是物件的預設值。 任何執行緒可以隨時存取任何方法或欄位。 一次應該只有一個執行緒存取這些物件。

手動同步

.NET Framework 類別庫提供一些類別來同步執行緒。 請參閱同步處理原始物件概觀

同步的程式碼區域

您可以使用 Monitor 類別或編譯器關鍵字,來同步處理程式碼區塊、執行個體方法以及靜態方法。 不支援同步處理的靜態欄位。

Visual Basic 和 C# 都支援使用特定語言關鍵字來標示程式碼區塊,在 C# 中為 lock陳述式,在 Visual Basic 中為 SyncLock 陳述式。 由執行緒執行程式碼時,會嘗試取得鎖定。 如果已經由另一個執行緒取得鎖定,則執行緒會封鎖,直到鎖定可用為止。 當執行緒結束已同步處理的程式碼區塊時,鎖定會被釋放,不論執行緒如何結束區塊。

注意

從 C# 13 開始,lock 陳述式會辨識鎖定的物件是否為 System.Threading.Lock 的執行個體,並使用 EnterScope 方法來建立同步的區域。 當目標不是 Lock 執行個體時,lockSyncLock 陳述式會使用 Monitor.EnterMonitor.Exit 來實作,讓 Monitor 的其他方法可在同步的區域內搭配它們使用。

您也可以使用值為 MethodImplOptions.SynchronizedMethodImplAttribute 來裝飾方法,其效果與使用 Monitor 或其中一個編譯器關鍵字來鎖定方法的整個主體相同。

Thread.Interrupt 可以用來中斷執行緒的封鎖作業,例如等待存取已同步處理的程式碼區域。 Thread.Interrupt 也會用來中斷執行緒的作業,例如 Thread.Sleep

重要

不要鎖定型別 — 也就是,C# 中的 typeof(MyType)、Visual Basic 中的 GetType(MyType)或 C++ 中的 MyType::typeid — 以便保護 static 方法 (Visual Basic 中的 Shared方法)。 請改為使用私用靜態物件。 同樣地,在 C# 中不要使用 this(在 Visual Basic 中不要使用 Me) 以鎖定執行個體方法。 請改為使用私用物件。 類別或執行個體會被您專屬的程式碼以外的程式碼鎖定,可能造成死結或效能問題。

編譯器支援

Visual Basic 和 C# 均支援使用 Monitor.EnterMonitor.Exit 來鎖定物件的語言關鍵字。 Visual Basic 支援 SyncLock 陳述式;C# 支援 lock 陳述式。

在這兩種情況下,如果在程式碼區塊中擲回例外狀況,lockSyncLock 取得的鎖定會自動釋放。 C# 和 Visual Basic 編譯器會在嘗試開始時發出 try/finally 區塊與 Monitor.Enter,以及在 finally 區塊中發出 Monitor.Exit。 如果在 lockSyncLock 區塊內擲回例外狀況,會執行 finally 處理常式以允許您進行任何清除工作。

同步處理的內容

僅限在 .NET Framework 和 Xamarin 應用程式中,您可以在任何 ContextBoundObject 上使用 SynchronizationAttribute 來同步所有執行個體方法和欄位。 相同內容網域中所有物件都共用相同的鎖定。 允許多個執行緒存取方法和欄位,但是一次只允許單一執行緒。

另請參閱