Ereignisse
Erstellen von KI-Apps und Agents
17. März, 21 Uhr - 21. März, 10 Uhr
Nehmen Sie an der Meetup-Serie teil, um skalierbare KI-Lösungen basierend auf realen Anwendungsfällen mit Mitentwicklern und Experten zu erstellen.
Jetzt registrierenDieser Browser wird nicht mehr unterstützt.
Führen Sie ein Upgrade auf Microsoft Edge durch, um die neuesten Features, Sicherheitsupdates und den technischen Support zu nutzen.
Ruft eine exklusive Sperre für einen Anweisungsblock ab, bevor der Block ausgeführt wird.
SyncLock lockobject
[ block ]
End SyncLock
lockobject
Erforderlich. Ausdruck, der einen Objektverweis auswertet.
block
Optional. Block von Anweisungen, die ausgeführt werden sollen, wenn die Sperre abgerufen wird.
End SyncLock
beendet einen SyncLock
-Block.
Die SyncLock
-Anweisung stellt sicher, dass nicht mehrere Threads gleichzeitig den Anweisungsblock ausführen. SyncLock
sorgt dafür, dass ein Thread den Block erst dann startet, wenn ihn kein anderer Thread mehr ausführt.
SyncLock
wird am häufigsten verwendet, um zu verhindern, dass Daten von mehreren Threads gleichzeitig aktualisiert werden. Wenn die Anweisungen, die die Daten bearbeiten, ohne Unterbrechung abgeschlossen werden müssen, platzieren Sie sie in einen SyncLock
-Block.
Ein Anweisungsblock, der durch eine exklusive Sperre geschützt wird, wird manchmal als kritischer Abschnitt bezeichnet.
Branchen. Eine Verzweigung in einen SyncLock
-Block von außerhalb ist nicht möglich.
Sperrobjekt-Wert. Der Wert von lockobject
kann nicht Nothing
sein. Sie müssen das Sperrobjekt erstellen, bevor Sie es in einer SyncLock
-Anweisung verwenden.
Sie können den Wert von lockobject
während der Ausführung eines SyncLock
-Blocks nicht ändern. Der Mechanismus setzt voraus, dass das Sperrobjekt nicht geändert wird.
Sie können den Await-Operator nicht in einem SyncLock
-Block verwenden.
Mechanismus. Wenn ein Thread die SyncLock
-Anweisung erreicht, wertet er den lockobject
-Ausdruck aus und setzt die Ausführung aus, bis er eine exklusive Sperre für das Objekt abgerufen hat, das vom Ausdruck zurückgegeben wird. Wenn ein weiterer Thread die SyncLock
-Anweisung erreicht, ruft er erst eine Sperre ab, wenn der erste Thread die End SyncLock
-Anweisung ausführt.
Geschützte Daten. Wenn lockobject
eine Shared
-Variable ist, verhindert die exklusive Sperre, dass ein Thread in einer Instanz der Klasse den SyncLock
-Block ausführt, während er von einem anderen Thread ausgeführt wird. So werden Daten geschützt, die von allen Instanzen gemeinsam genutzt werden.
Wenn lockobject
eine Instanzvariable ist (nicht Shared
), verhindert die Sperre, dass ein Thread, der in der aktuellen Instanz ausgeführt wird, den SyncLock
-Block zur selben Zeit ausführt wie ein anderer Thread in derselben Instanz. So werden Daten geschützt, die von der einzelnen Instanz verwaltet werden.
Abruf und Freigabe. Ein SyncLock
-Block verhält sich wie eine Try...Finally
-Konstruktion, in der der Try
-Block eine exklusive Sperre für lockobject
abruft und der Finally
-Block sie freigibt. Aus diesem Grund gewährleistet der SyncLock
-Block die Freigabe der Sperre, unabhängig davon, wie Sie den Block verlassen. Das gilt selbst im Falle eines Ausnahmefehlers.
Framework-Aufrufe. Der SyncLock
-Block ruft die exklusive Sperre ab und gibt sie wieder frei, indem er die Methoden Enter
und Exit
der Klasse Monitor
im Namespace System.Threading aufruft.
Der Ausdruck lockobject
sollte immer zu einem Objekt ausgewertet werden, das exklusiv zu Ihrer Klasse gehört. Sie sollten eine Private
-Objektvariable so deklarieren, dass die Daten, die zur aktuellen Instanz gehören, geschützt werden, und eine Private Shared
-Objektvariable so, dass die Daten, die von allen Instanzen genutzt werden, geschützt werden.
Sie sollten das Schlüsselwort Me
nicht dazu verwenden, ein Sperrobjekt für Instanzdaten bereitzustellen. Wenn Code außerhalb Ihrer Klasse auf eine Instanz Ihrer Klasse verweist, könnte er diesen Verweis als Sperrobjekt für einen SyncLock
-Block verwenden, der völlig von Ihrem abweicht, sodass unterschiedliche Daten geschützt werden. So könnte es dazu kommen, dass Ihre Klasse und die andere Klasse sich gegenseitig davon abhalten, die nicht zusammenhängenden SyncLock
-Blöcke auszuführen. Auch die Sperre für eine Zeichenfolge kann problematisch sein, da jeder andere Code im Prozess, der dieselbe Zeichenfolge verwendet, auch dieselbe Sperre verwendet.
Sie sollten die Me.GetType
-Methode auch nicht dazu verwenden, ein Sperrobjekt für freigegebene Daten bereitzustellen. Grund dafür ist, dass GetType
immer dasselbe Type
-Objekt für einen Klassennamen zurückgibt. Externer Code könnte GetType
in Ihrer Klasse aufrufen und dasselbe Sperrobjekt abrufen, das Sie gerade verwenden. Dies würde dazu führen, dass die zwei Klassen sich gegenseitig davon abhalten, ihre SyncLock
-Blöcke auszuführen.
Das folgende Beispiel zeigt eine Klasse, die eine einfache Liste an Nachrichten verwaltet. Die Nachrichten sind in einem Array enthalten, und das zuletzt verwendete Element dieses Arrays ist in einer Variablen enthalten. Die addAnotherMessage
-Prozedur erhöht das letzte Element und speichert es in einer neuen Nachricht. Diese zwei Vorgänge werden durch die SyncLock
- und End SyncLock
-Anweisungen geschützt, da nach dem Erhöhen des letzten Elements die neue Nachricht gespeichert werden muss, bevor ein anderer Thread das letzte Element erneut erhöhen kann.
Falls die Klasse simpleMessageList
eine Liste an Nachrichten für alle Instanzen freigegeben hat, würden die Variablen messagesList
und messagesLast
als Shared
deklariert werden. In diesem Fall sollte die Variable messagesLock
ebenfalls Shared
sein, damit es ein einziges Sperrobjekt gibt, das von jeder Instanz verwendet wird.
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
Das folgende Beispiel verwendet Threads und SyncLock
. Solange die SyncLock
-Anweisung vorhanden ist, ist der Anweisungsblock ein kritischer Abschnitt und balance
wird niemals eine negative Zahl. Sie können die SyncLock
- und End SyncLock
-Anweisungen auskommentieren, um zu testen, welche Auswirkung das Weglassen des Schlüsselworts SyncLock
hat.
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
Feedback zu .NET
.NET ist ein Open Source-Projekt. Wählen Sie einen Link aus, um Feedback zu geben:
Ereignisse
Erstellen von KI-Apps und Agents
17. März, 21 Uhr - 21. März, 10 Uhr
Nehmen Sie an der Meetup-Serie teil, um skalierbare KI-Lösungen basierend auf realen Anwendungsfällen mit Mitentwicklern und Experten zu erstellen.
Jetzt registrieren