Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Erwirbt eine exklusive Sperre für einen Anweisungsblock, bevor der Block ausgeführt wird.
Syntax
SyncLock lockobject
[ block ]
End SyncLock
Bestandteile
lockobject
Erforderlich. Ausdruck, der zu einem Objektverweis ausgewertet wird.
block
Wahlfrei. Block von Anweisungen, die ausgeführt werden sollen, wenn die Sperre abgerufen wird.
End SyncLock
Beendet einen SyncLock
Block.
Bemerkungen
Die SyncLock
Anweisung stellt sicher, dass mehrere Threads den Anweisungsblock nicht gleichzeitig ausführen.
SyncLock
verhindert, dass jeder Thread den Block eingibt, bis kein anderer Thread ausgeführt wird.
Die häufigste Verwendung SyncLock
besteht darin, Daten vor gleichzeitiger Aktualisierung durch mehrere Threads zu schützen. Wenn die Anweisungen, die die Daten bearbeiten, ohne Unterbrechung abgeschlossen werden müssen, platzieren Sie sie in einem SyncLock
Block.
Ein durch eine exklusive Sperre geschützter Anweisungsblock wird manchmal als kritischer Abschnitt bezeichnet.
Regeln
Verzweigung. Sie können nicht von außerhalb des Blocks in einen
SyncLock
Block verzweigen.Sperrobjektwert. Der Wert darf
lockobject
nicht seinNothing
. Sie müssen das Sperrobjekt erstellen, bevor Sie es in einerSyncLock
Anweisung verwenden.Sie können den Wert der
lockobject
Ausführung einesSyncLock
Blocks nicht ändern. Der Mechanismus erfordert, dass das Sperrobjekt unverändert bleibt.Sie können den Await-Operator nicht in einem
SyncLock
Block verwenden.
Verhalten
Mechanismus. Wenn ein Thread die
SyncLock
Anweisung erreicht, wertet er denlockobject
Ausdruck aus und hält die Ausführung an, bis er eine exklusive Sperre für das vom Ausdruck zurückgegebene Objekt erhält. Wenn ein anderer Thread dieSyncLock
Anweisung erreicht, erhält er erst eine Sperre, wenn der erste Thread dieEnd SyncLock
Anweisung ausführt.Geschützte Daten. Wenn
lockobject
es sich um eineShared
Variable handelt, verhindert die exklusive Sperre, dass ein Thread in jeder Instanz der Klasse denSyncLock
Block ausführt, während ein anderer Thread ihn ausführt. Dadurch werden Daten geschützt, die von allen Instanzen gemeinsam genutzt werden.Wenn
lockobject
es sich um eine Instanzvariable (nichtShared
) handelt, verhindert die Sperre, dass ein Thread, der in der aktuellen Instanz ausgeführt wird, denSyncLock
Block gleichzeitig mit einem anderen Thread in derselben Instanz ausführt. Dadurch werden die von der einzelnen Instanz verwalteten Daten geschützt.Erwerb und Freigabe. Ein
SyncLock
Block verhält sich wie eineTry...Finally
Konstruktion, in der derTry
Block eine exklusive Sperrelockobject
erhält und derFinally
Block loslässt. Aus diesem Gründen garantiert derSyncLock
Block die Freigabe der Sperre, unabhängig davon, wie Sie den Block verlassen. Dies gilt auch bei einer unbehandelten Ausnahme.Framework-Aufrufe. Der
SyncLock
Block erwirbt und gibt die exklusive Sperre frei, indem dieEnter
Klassen undExit
MethodenMonitor
im System.Threading Namespace aufgerufen werden.
Programmierpraktiken
Der lockobject
Ausdruck sollte immer zu einem Objekt ausgewertet werden, das ausschließlich zu Ihrer Klasse gehört. Sie sollten eine Private
Objektvariable deklarieren, um Daten zu schützen, die zur aktuellen Instanz gehören, oder eine Private Shared
Objektvariable zum Schutz von Daten, die allen Instanzen gemeinsam sind.
Sie sollten das Me
Schlüsselwort nicht verwenden, um ein Sperrobjekt für Instanzdaten bereitzustellen. Wenn der externe Code ihrer Klasse über einen Verweis auf eine Instanz Ihrer Klasse verfügt, kann dieser Verweis als Sperrobjekt für einen SyncLock
Block verwendet werden, der sich vollständig von Ihren unterscheidet und unterschiedliche Daten schützt. Auf diese Weise könnte Ihre Klasse und die andere Klasse verhindern, dass ihre nicht verknüpften SyncLock
Blöcke ausgeführt werden. Ebenso kann die Sperre für eine Zeichenfolge problematisch sein, da jeder andere Code im Prozess mit derselben Zeichenfolge dieselbe Sperre gemeinsam verwendet.
Sie sollten auch nicht die Me.GetType
Methode verwenden, um ein Sperrobjekt für freigegebene Daten bereitzustellen. Dies liegt daran, dass GetType
immer dasselbe Type
Objekt für einen bestimmten Klassennamen zurückgegeben wird. Externer Code kann Ihre Klasse aufrufen GetType
und dasselbe Sperrobjekt abrufen, das Sie verwenden. Dies würde dazu führen, dass sich die beiden Klassen gegenseitig von ihren SyncLock
Blöcken blockieren.
Beispiele
BESCHREIBUNG
Das folgende Beispiel zeigt eine Klasse, die eine einfache Liste von Nachrichten verwaltet. Sie enthält die Nachrichten in einem Array und das zuletzt verwendete Element dieses Arrays in einer Variablen. Die addAnotherMessage
Prozedur erhöht das letzte Element und speichert die neue Nachricht. Diese beiden Vorgänge werden durch die SyncLock
Anweisungen End SyncLock
geschützt, da die neue Nachricht gespeichert werden muss, sobald das letzte Element erhöht wurde, bevor ein anderer Thread das letzte Element erneut erhöhen kann.
Wenn die simpleMessageList
Klasse eine Liste von Nachrichten unter allen Instanzen freigegeben hat, werden die Variablen messagesList
messagesLast
als Shared
deklariert. In diesem Fall sollte die Variable messagesLock
auch sein Shared
, sodass es ein einzelnes Sperrobjekt gibt, das von jeder Instanz verwendet wird.
Programmcode
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
BESCHREIBUNG
Im folgenden Beispiel werden Threads und SyncLock
. Solange die Anweisung vorhanden ist, ist der SyncLock
Anweisungsblock ein kritischer Abschnitt und balance
wird nie zu einer negativen Zahl. Sie können die SyncLock
Und-Anweisungen End SyncLock
kommentieren, um den Effekt zu sehen, dass das SyncLock
Schlüsselwort verlassen wird.
Programmcode
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