Note
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier les répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de changer de répertoire.
Acquiert un verrou exclusif pour un bloc d’instructions avant d’exécuter le bloc.
Syntaxe
SyncLock lockobject
[ block ]
End SyncLock
Pièces
lockobject
Obligatoire. Expression qui prend la valeur d’une référence d’objet.
block
Optionnel. Bloc d’instructions à exécuter lorsque le verrou est acquis.
End SyncLock
Met fin à un SyncLock bloc.
Remarques
L’instruction SyncLock garantit que plusieurs threads n’exécutent pas le bloc d’instructions en même temps.
SyncLock empêche chaque thread d’entrer dans le bloc tant qu’aucun autre thread ne l’exécute.
L’utilisation la plus courante consiste SyncLock à protéger les données contre la mise à jour simultanée de plusieurs threads. Si les instructions qui manipulent les données doivent être terminées sans interruption, placez-les dans un SyncLock bloc.
Un bloc d’instructions protégé par un verrou exclusif est parfois appelé section critique.
Règles
Ramification. Vous ne pouvez pas vous brancher dans un
SyncLockbloc à partir de l’extérieur du bloc.Valeur de l’objet Lock. La valeur de
lockobjectne peut pas êtreNothing. Vous devez créer l’objet de verrou avant de l’utiliser dans uneSyncLockinstruction.Vous ne pouvez pas modifier la valeur d’un bloc lors de
lockobjectl’exécution d’unSyncLockbloc. Le mécanisme exige que l’objet de verrou reste inchangé.Vous ne pouvez pas utiliser l’opérateur Await dans un
SyncLockbloc.
Comportement
Mécanisme. Lorsqu’un thread atteint l’instruction
SyncLock, il évalue l’expression et suspend l’exécutionlockobjectjusqu’à ce qu’elle acquiert un verrou exclusif sur l’objet retourné par l’expression. Lorsqu’un autre thread atteint l’instructionSyncLock, il n’acquiert pas de verrou tant que le premier thread n’exécute pas l’instructionEnd SyncLock.Données protégées. S’il
lockobjects’agit d’uneSharedvariable, le verrou exclusif empêche un thread dans une instance de la classe d’exécuter leSyncLockbloc alors que tout autre thread l’exécute. Cela protège les données partagées entre toutes les instances.S’il
lockobjects’agit d’une variable d’instance (et nonShared), le verrou empêche un thread en cours d’exécution dans l’instance actuelle d’exécuter leSyncLockbloc en même temps qu’un autre thread de la même instance. Cela protège les données conservées par l’instance individuelle.Acquisition et mise en production. Un
SyncLockbloc se comporte comme uneTry...Finallyconstruction dans laquelle leTrybloc acquiert un verrou exclusif surlockobjectet leFinallybloc le libère. En raison de cela, leSyncLockbloc garantit la libération du verrou, quelle que soit la façon dont vous quittez le bloc. Cela est vrai même dans le cas d’une exception non gérée.Appels d’infrastructure. Le
SyncLockbloc acquiert et libère le verrou exclusif en appelant les méthodes etExitlesEnterméthodes de laMonitorclasse dans l’espace System.Threading de noms.
Pratiques de programmation
L’expression lockobject doit toujours évaluer un objet qui appartient exclusivement à votre classe. Vous devez déclarer une Private variable objet pour protéger les données appartenant à l’instance actuelle ou une Private Shared variable objet pour protéger les données communes à toutes les instances.
Vous ne devez pas utiliser le Me mot clé pour fournir un objet de verrouillage pour les données d’instance. Si le code externe à votre classe a une référence à une instance de votre classe, il peut utiliser cette référence en tant qu’objet de verrou pour un SyncLock bloc complètement différent du vôtre, protégeant des données différentes. De cette façon, votre classe et l’autre classe peuvent empêcher l’exécution de leurs blocs non liés SyncLock . De même, le verrouillage sur une chaîne peut être problématique, car tout autre code du processus utilisant la même chaîne partagera le même verrou.
Vous ne devez pas également utiliser la Me.GetType méthode pour fournir un objet de verrouillage pour les données partagées. Cela est dû au fait que GetType toujours retourne le même Type objet pour un nom de classe donné. Le code externe peut appeler GetType votre classe et obtenir le même objet de verrouillage que celui que vous utilisez. Cela entraînerait le blocage des deux classes les unes des autres de leurs SyncLock blocs.
Exemples
Descriptif
L’exemple suivant montre une classe qui gère une liste simple de messages. Il contient les messages d’un tableau et le dernier élément utilisé de ce tableau dans une variable. La addAnotherMessage procédure incrémente le dernier élément et stocke le nouveau message. Ces deux opérations sont protégées par les SyncLock instructions et End SyncLock , étant donné qu’une fois le dernier élément incrémenté, le nouveau message doit être stocké avant que tout autre thread puisse incrémenter le dernier élément.
Si la simpleMessageList classe a partagé une liste de messages parmi toutes ses instances, les variables messagesList et messagesLast seraient déclarées en tant que Shared. Dans ce cas, la variable messagesLock doit également être Shared, afin qu’il y ait un seul objet de verrou utilisé par chaque instance.
Code
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
Descriptif
L’exemple suivant utilise des threads et SyncLock. Tant que l’instruction SyncLock est présente, le bloc d’instructions est une section critique et balance ne devient jamais un nombre négatif. Vous pouvez commenter les SyncLock instructions et End SyncLock afficher l’effet de l’abandon du SyncLock mot clé.
Code
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