Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Acquisisce un blocco esclusivo per un blocco di istruzioni prima di eseguire il blocco.
Sintassi
SyncLock lockobject
[ block ]
End SyncLock
Parti
lockobject
Obbligatorio. Espressione che restituisce un riferimento a un oggetto.
block
Opzionale. Blocco di istruzioni da eseguire quando viene acquisito il blocco.
End SyncLock
Termina un SyncLock blocco.
Osservazioni:
L'istruzione SyncLock garantisce che più thread non eseseguono contemporaneamente il blocco di istruzioni.
SyncLock impedisce a ogni thread di immettere il blocco fino a quando non viene eseguito alcun altro thread.
L'uso più comune di SyncLock consiste nel proteggere i dati dall'aggiornamento simultaneo di più thread. Se le istruzioni che modificano i dati devono andare al completamento senza interruzioni, inserirle 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 un ramo in un
SyncLockblocco dall'esterno del blocco.Valore dell'oggetto Lock. Il valore di
lockobjectnon può essereNothing. È necessario creare l'oggetto lock prima di usarlo in un'istruzioneSyncLock.Non è possibile modificare il valore di durante l'esecuzione di
lockobjectunSyncLockblocco. Il meccanismo richiede che l'oggetto lock rimanga invariato.Non è possibile usare l'operatore Await in un
SyncLockblocco.
Comportamento
Meccanismo. Quando un thread raggiunge l'istruzione
SyncLock, valuta l'espressione e sospende l'esecuzionelockobjectfinché non acquisisce un blocco esclusivo sull'oggetto restituito dall'espressione. Quando un altro thread raggiunge l'istruzioneSyncLock, non acquisisce un blocco finché il primo thread non esegue l'istruzioneEnd SyncLock.Dati protetti. Se
lockobjectè unaSharedvariabile, il blocco esclusivo impedisce a un thread in qualsiasi istanza della classe di eseguire ilSyncLockblocco mentre è in esecuzione qualsiasi altro thread. In questo modo vengono protetti i dati condivisi tra tutte le istanze.Se
lockobjectè una variabile di istanza (nonShared), il blocco impedisce a un thread in esecuzione nell'istanza corrente di eseguire ilSyncLockblocco contemporaneamente a un altro thread nella stessa istanza. In questo modo vengono protetti i dati gestiti dalla singola istanza.Acquisizione e rilascio. Un
SyncLockblocco si comporta come unaTry...Finallycostruzione in cui ilTryblocco acquisisce un blocco esclusivo sulockobjecte ilFinallyblocco lo rilascia. Per questo motivo, il blocco garantisce ilSyncLockrilascio del blocco, indipendentemente dal modo in cui si esce dal blocco. Questo vale anche nel caso di un'eccezione non gestita.Chiamate al framework. Il
SyncLockblocco acquisisce e rilascia il blocco esclusivo chiamando iEntermetodi eExitdellaMonitorclasse nello spazio dei System.Threading nomi .
Procedure di programmazione
L'espressione lockobject 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 Private Shared variabile oggetto per proteggere i dati comuni a tutte le istanze.
Non usare la Me parola chiave per fornire un oggetto lock per i dati di istanza. Se il codice esterno alla classe ha un riferimento a un'istanza della classe, può usare tale riferimento come oggetto lock per un SyncLock blocco completamente diverso da quello dell'utente, proteggendo dati diversi. In questo modo, la classe e l'altra classe potrebbero impedire l'esecuzione dei blocchi non correlati SyncLock . 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 usare il Me.GetType metodo per fornire un oggetto lock per i dati condivisi. Ciò è dovuto al fatto che GetType restituisce sempre lo stesso Type oggetto per un determinato nome di classe. Il codice esterno può chiamare GetType la classe e ottenere lo stesso oggetto di blocco in uso. In questo modo, le due classi bloccano l'una dall'altra dai relativi SyncLock blocchi.
Esempi
Descrizione
Nell'esempio seguente viene illustrata una classe che gestisce un elenco semplice 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 SyncLock istruzioni e End SyncLock , perché una volta incrementato l'ultimo elemento, il nuovo messaggio deve essere archiviato prima che qualsiasi altro thread possa incrementare nuovamente l'ultimo elemento.
Se la simpleMessageList classe ha condiviso un elenco di messaggi tra tutte le relative istanze, le variabili messagesList e messagesLast verranno dichiarate come Shared. In questo caso, la variabile messagesLock deve anche essere Shared, in modo che ci sia un singolo oggetto lock usato da ogni 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 usati thread e SyncLock. Se l'istruzione SyncLock è presente, il blocco di istruzioni è una sezione critica e balance non diventa mai un numero negativo. È possibile impostare come commento le SyncLock istruzioni e End SyncLock per visualizzare l'effetto di uscire dalla SyncLock parola 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