Freigeben über


SyncLock-Anweisung

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 sein Nothing. Sie müssen das Sperrobjekt erstellen, bevor Sie es in einer SyncLock Anweisung verwenden.

    Sie können den Wert der lockobject Ausführung eines SyncLock 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 den lockobject 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 die SyncLock Anweisung erreicht, erhält er erst eine Sperre, wenn der erste Thread die End SyncLock Anweisung ausführt.

  • Geschützte Daten. Wenn lockobject es sich um eine Shared Variable handelt, verhindert die exklusive Sperre, dass ein Thread in jeder Instanz der Klasse den SyncLock 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 (nicht Shared) handelt, verhindert die Sperre, dass ein Thread, der in der aktuellen Instanz ausgeführt wird, den SyncLock 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 eine Try...Finally Konstruktion, in der der Try Block eine exklusive Sperre lockobject erhält und der Finally Block loslässt. Aus diesem Gründen garantiert der SyncLock 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 die Enter Klassen und Exit Methoden Monitor 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 messagesListmessagesLast als Shareddeklariert. 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

Kommentare

Siehe auch