在執行 區塊之前,先取得語句區塊的獨佔鎖定。
語法
SyncLock lockobject
[ block ]
End SyncLock
組件
lockobject
必須的。 評估為對象參考的表達式。
block
選擇性。 取得鎖定時要執行的語句區塊。
End SyncLock
SyncLock終止區塊。
備註
語句 SyncLock 可確保多個線程不會同時執行語句區塊。
SyncLock 防止每個線程進入 區塊,直到沒有其他線程執行它為止。
最常見的用法 SyncLock 是保護數據免於同時由一個以上的線程更新。 如果作數據的語句必須移至完成,而不會中斷,請將它們放在區塊內 SyncLock 。
受獨佔鎖定保護的語句區塊有時稱為 重要區段。
規則
分支。 您無法從 區塊外部分支至
SyncLock區塊。Lock 物件值。 的值
lockobject不可以是Nothing。 在語句中使用SyncLock鎖定物件之前,您必須先建立鎖定物件。您無法在執行
SyncLock區塊時變更的值lockobject。 機制要求鎖定物件保持不變。您無法在 區塊中使用
SyncLockAwait 運算子。
行為
機制。 當線程到達
SyncLock語句時lockobject,它會評估表達式並暫停執行,直到它取得表達式所傳回物件的獨佔鎖定為止。 當另一個線程到達SyncLock語句時,它不會取得鎖定,直到第一個線程執行End SyncLock語句為止。受保護的數據。 如果
lockobject是Shared變數,則獨佔鎖定可防止類別的任何實例中的線程在執行區塊時執行SyncLock區塊。 這會保護所有實例之間共享的數據。如果
lockobject是實例變數(不是Shared),鎖定會防止在目前實例中執行的線程與相同實例中的另一個線程同時執行SyncLock區塊。 這會保護個別實例所維護的數據。取得和發行。
SyncLock區塊的行為就像Try...Finally區塊取得獨佔鎖定lockobject的建構Try,而Finally區塊會釋放它。 因此,SyncLock不論您如何結束區塊,區塊都保證會釋放鎖定。 即使發生未處理的例外狀況,也是如此。架構呼叫。 區塊
SyncLock會藉由在 命名空間中System.Threading呼叫Enter類別的Monitor和Exit方法,來取得並釋放獨佔鎖定。
程序設計實務
表達式 lockobject 應該一律評估為專屬於類別的物件。 您應該宣告 Private 物件變數來保護屬於目前實例的數據,或 Private Shared 宣告物件變數來保護所有實例通用的數據。
您不應該使用 Me 關鍵詞來提供實例數據的鎖定物件。 如果類別外部的程式代碼具有類別實例的參考,它可以使用該參考做為與您完全不同的區塊鎖定對象 SyncLock ,保護不同的數據。 如此一來,您的類別和另一個類別可能會互相封鎖,使其無法執行其不相關的 SyncLock 區塊。 同樣地,鎖定字串可能會造成問題,因為進程中使用相同字串的任何其他程式碼都會共用相同的鎖定。
您也不應該使用 Me.GetType 方法來提供共享數據的鎖定物件。 這是因為 GetType 一律會針對指定的類別名稱傳回相同的 Type 物件。 外部程式代碼可以在類別上呼叫 GetType ,並取得您所使用的相同鎖定物件。 這會導致兩個類別彼此封鎖其 SyncLock 區塊。
範例
說明
下列範例顯示維護簡單訊息清單的類別。 它會保存數位中的訊息,以及變數中該陣列的最後一個已使用元素。 此 addAnotherMessage 程式會遞增最後一個專案,並儲存新的訊息。 這兩個作業會受到 SyncLock 和 End SyncLock 語句的保護,因為一旦最後一個專案遞增,必須先儲存新的訊息,任何其他線程才能再次遞增最後一個專案。
simpleMessageList如果類別在其所有實體之間共用一份訊息清單,messagesList變數和 messagesLast 會宣告為 Shared。 在此情況下,變數 messagesLock 也應該是 Shared,因此每個實例都會使用單一鎖定物件。
Code
Class simpleMessageList
Public messagesList() As String = New String(50) {}
Public messagesLast As Integer = -1
Private messagesLock As New Object
Public Sub addAnotherMessage(ByVal newMessage As String)
SyncLock messagesLock
messagesLast += 1
If messagesLast < messagesList.Length Then
messagesList(messagesLast) = newMessage
End If
End SyncLock
End Sub
End Class
說明
下列範例使用線程和 SyncLock。 只要 SyncLock 語句存在,語句區塊就是關鍵區段,而且 balance 永遠不會變成負數。 您可以批注化 SyncLock 和 End SyncLock 語句,以查看排除 SyncLock 關鍵詞的效果。
Code
Imports System.Threading
Module Module1
Class Account
Dim thisLock As New Object
Dim balance As Integer
Dim r As New Random()
Public Sub New(ByVal initial As Integer)
balance = initial
End Sub
Public Function Withdraw(ByVal amount As Integer) As Integer
' This condition will never be true unless the SyncLock statement
' is commented out:
If balance < 0 Then
Throw New Exception("Negative Balance")
End If
' Comment out the SyncLock and End SyncLock lines to see
' the effect of leaving out the SyncLock keyword.
SyncLock thisLock
If balance >= amount Then
Console.WriteLine("Balance before Withdrawal : " & balance)
Console.WriteLine("Amount to Withdraw : -" & amount)
balance = balance - amount
Console.WriteLine("Balance after Withdrawal : " & balance)
Return amount
Else
' Transaction rejected.
Return 0
End If
End SyncLock
End Function
Public Sub DoTransactions()
For i As Integer = 0 To 99
Withdraw(r.Next(1, 100))
Next
End Sub
End Class
Sub Main()
Dim threads(10) As Thread
Dim acc As New Account(1000)
For i As Integer = 0 To 9
Dim t As New Thread(New ThreadStart(AddressOf acc.DoTransactions))
threads(i) = t
Next
For i As Integer = 0 To 9
threads(i).Start()
Next
End Sub
End Module