Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
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
SyncLock
bloc à partir de l’extérieur du bloc.Valeur de l’objet Lock. La valeur de
lockobject
ne peut pas êtreNothing
. Vous devez créer l’objet de verrou avant de l’utiliser dans uneSyncLock
instruction.Vous ne pouvez pas modifier la valeur d’un bloc lors de
lockobject
l’exécution d’unSyncLock
bloc. Le mécanisme exige que l’objet de verrou reste inchangé.Vous ne pouvez pas utiliser l’opérateur Await dans un
SyncLock
bloc.
Comportement
Mécanisme. Lorsqu’un thread atteint l’instruction
SyncLock
, il évalue l’expression et suspend l’exécutionlockobject
jusqu’à 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
lockobject
s’agit d’uneShared
variable, le verrou exclusif empêche un thread dans une instance de la classe d’exécuter leSyncLock
bloc alors que tout autre thread l’exécute. Cela protège les données partagées entre toutes les instances.S’il
lockobject
s’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 leSyncLock
bloc 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
SyncLock
bloc se comporte comme uneTry...Finally
construction dans laquelle leTry
bloc acquiert un verrou exclusif surlockobject
et leFinally
bloc le libère. En raison de cela, leSyncLock
bloc 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
SyncLock
bloc acquiert et libère le verrou exclusif en appelant les méthodes etExit
lesEnter
méthodes de laMonitor
classe 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