Istruzione SyncLock

Acquisisce un blocco esclusivo per un blocco di istruzioni prima di eseguirne il blocco.

Sintassi

SyncLock lockobject  
    [ block ]  
End SyncLock  

Parti

lockobject
Obbligatorio. Espressione che restituisce un riferimento a un oggetto.

block
facoltativo. Blocco di istruzioni da eseguire quando viene acquisito il blocco.

End SyncLock
Termina un SyncLock blocco .

Commenti

SyncLockL'istruzione garantisce che più thread non esercitino il blocco di istruzioni contemporaneamente. SyncLock impedisce a ogni thread di accedere al blocco fino a quando non viene eseguito da nessun altro thread.

L'uso più comune di è quello di proteggere i dati dall'aggiornamento di SyncLock più thread contemporaneamente. Se le istruzioni che modificano i dati devono essere completate senza interruzioni, inserire le istruzioni all'interno di un SyncLock blocco .

Un blocco di istruzioni protetto da un blocco esclusivo viene talvolta definito sezione critica.

Regole

  • Ramificazione. Non è possibile creare rami in SyncLock un blocco dall'esterno del blocco.

  • Valore dell'oggetto di blocco. Il valore di lockobject non può essere Nothing . È necessario creare l'oggetto blocco prima di usarlo in SyncLock un'istruzione .

    Non è possibile modificare il valore di lockobject durante l'esecuzione di un SyncLock blocco . Il meccanismo richiede che l'oggetto blocco rimanga invariato.

  • Non è possibile usare l'operatore Await in un SyncLock blocco .

Comportamento

  • Meccanismo. Quando un thread raggiunge l'istruzione, valuta l'espressione e sospende l'esecuzione finché non acquisisce un blocco esclusivo SyncLock lockobject sull'oggetto restituito dall'espressione. Quando un altro thread raggiunge SyncLock l'istruzione, non acquisisce un blocco fino a quando il primo thread non esegue End SyncLock l'istruzione.

  • Dati protetti. Se è una variabile, il blocco esclusivo impedisce a un thread in qualsiasi istanza della classe di eseguire il blocco mentre è in esecuzione lockobject Shared da qualsiasi altro SyncLock thread. In questo modo si proteggono i dati condivisi tra tutte le istanze.

    Se è una variabile di istanza (non ), il blocco impedisce a un thread in esecuzione nell'istanza corrente di eseguire il blocco contemporaneamente a un altro lockobject Shared thread nella stessa SyncLock istanza. In questo modo si proteggono i dati gestiti dalla singola istanza.

  • Acquisizione e rilascio. Un SyncLock blocco si comporta come una costruzione in cui il blocco acquisisce un blocco esclusivo su e il blocco lo Try...Finally Try lockobject Finally rilascia. Per questo, il SyncLock blocco garantisce il rilascio del blocco, indipendentemente dalla modalità di uscita dal blocco. Questo vale anche nel caso di un'eccezione non gestita.

  • Chiamate al framework. Il SyncLock blocco acquisisce e rilascia il blocco esclusivo chiamando i Enter metodi e della classe nello spazio dei nomi Exit Monitor System.Threading .

Procedure di programmazione

lockobjectL'espressione deve sempre restituire un oggetto che appartiene esclusivamente alla classe. È necessario dichiarare una Private variabile oggetto per proteggere i dati appartenenti all'istanza corrente o una variabile oggetto per proteggere i dati comuni a tutte le Private Shared istanze.

È consigliabile non usare la parola Me chiave per fornire un oggetto lock per i dati dell'istanza. Se il codice esterno alla classe contiene un riferimento a un'istanza della classe, può usare tale riferimento come oggetto di blocco per un blocco completamente diverso dal proprio, proteggendo dati SyncLock diversi. In questo modo, la classe e l'altra classe potrebbero impedire l'esecuzione reciproca dei blocchi non SyncLock correlati. Analogamente, il blocco su una stringa può essere problematico perché qualsiasi altro codice nel processo che usa la stessa stringa condividerà lo stesso blocco.

È inoltre consigliabile non utilizzare il Me.GetType metodo per fornire un oggetto blocco per i dati condivisi. Ciò è dovuto al GetType fatto che restituisce sempre lo stesso oggetto per un nome di classe Type specificato. Il codice esterno può GetType chiamare sulla classe e ottenere lo stesso oggetto blocco in uso. In questo modo le due classi si bloccano a vicenda dai relativi SyncLock blocchi.

Esempi

Descrizione

Nell'esempio seguente viene illustrata una classe che gestisce un semplice elenco di messaggi. Contiene i messaggi in una matrice e l'ultimo elemento usato di tale matrice in una variabile. La addAnotherMessage routine incrementa l'ultimo elemento e archivia il nuovo messaggio. Queste due operazioni sono protette dalle istruzioni e , perché dopo l'incremento dell'ultimo elemento, il nuovo messaggio deve essere archiviato prima che qualsiasi altro thread possa incrementare nuovamente SyncLock End SyncLock l'ultimo elemento.

Se la classe condividesse un elenco di messaggi tra tutte le relative istanze, le variabili simpleMessageList messagesList e messagesLast verrebbero dichiarate come Shared . In questo caso, anche la variabile deve essere , in modo che sia presente un singolo oggetto messagesLock blocco usato da ogni Shared istanza.

Codice

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

Descrizione

Nell'esempio seguente vengono utilizzati i thread e SyncLock . Finché SyncLock l'istruzione è presente, il blocco di istruzioni è una sezione critica e balance non diventa mai un numero negativo. È possibile impostare come commento SyncLock le istruzioni e per vedere End SyncLock l'effetto di osare la parola SyncLock chiave .

Codice

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

Commenti

Vedi anche