SyncLock (Instrucción)
Adquiere un bloqueo exclusivo para un bloque de instrucciones antes de ejecutar el bloque .
Sintaxis
SyncLock lockobject
[ block ]
End SyncLock
Partes
lockobject
Necesario. Expresión que se evalúa como una referencia de objeto.
block
Opcional. Bloque de instrucciones que se van a ejecutar cuando se adquiere el bloqueo.
End SyncLock
Finaliza un SyncLock bloque.
Comentarios
La SyncLock instrucción garantiza que varios subprocesos no ejecuten el bloque de instrucciones al mismo tiempo. SyncLock impide que cada subproceso entre en el bloque hasta que ningún otro subproceso lo ejecute.
El uso más común de es proteger los datos de que varios subprocesos actualicen SyncLock los datos simultáneamente. Si las instrucciones que manipulan los datos deben completarse sin interrupción, pónlas dentro de un SyncLock bloque .
A veces, un bloque de instrucciones protegido por un bloqueo exclusivo se denomina sección crítica.
Reglas
Ramificación. No se puede bifurcar en
SyncLockun bloque desde fuera del bloque.Bloquear valor de objeto. El valor de
lockobjectno puede serNothing. Debe crear el objeto de bloqueo antes de usarlo en unaSyncLockinstrucción .No se puede cambiar el valor de
lockobjectmientras se ejecuta un bloqueSyncLock. El mecanismo requiere que el objeto de bloqueo permanezca sin cambios.No se puede usar el operador Await en un
SyncLockbloque .
Comportamiento
Mecanismo. Cuando un subproceso alcanza la instrucción , evalúa la expresión y suspende la ejecución hasta que adquiere un bloqueo exclusivo en el objeto
SyncLocklockobjectdevuelto por la expresión. Cuando otro subproceso alcanzaSyncLockla instrucción , no adquiere un bloqueo hasta que el primer subproceso ejecuta la instrucciónEnd SyncLock.Datos protegidos. Si es una variable, el bloqueo exclusivo impide que un subproceso de cualquier instancia de la clase ejecute el bloque mientras cualquier otro subproceso
lockobjectSharedloSyncLockejecuta. Esto protege los datos que se comparten entre todas las instancias.Si es una variable de instancia (no ), el bloqueo impide que un subproceso que se ejecuta en la instancia actual ejecute el bloque al mismo tiempo que otro subproceso
lockobjectSharedde la mismaSyncLockinstancia. Esto protege los datos mantenidos por la instancia individual.Adquisición y lanzamiento. Un bloque se comporta como una construcción en la que el bloque adquiere un bloqueo exclusivo
SyncLocken y el bloque loTry...FinallyTrylockobjectFinallylibera. Por este problema, elSyncLockbloque garantiza la liberación del bloqueo, independientemente de cómo salga del bloque. Esto es así incluso en el caso de una excepción no controlada.Llamadas de marco de trabajo. El bloque adquiere y libera el bloqueo exclusivo llamando a
SyncLocklos métodosEntery de la clase en el espacio de nombresExitMonitorSystem.Threading .
Prácticas de programación
La lockobject expresión siempre debe evaluarse como un objeto que pertenece exclusivamente a la clase . Debe declarar una variable de objeto para proteger los datos que pertenecen a la instancia actual o una variable de objeto para proteger los datos comunes Private a Private Shared todas las instancias.
No debe usar la palabra Me clave para proporcionar un objeto de bloqueo para los datos de instancia. Si el código externo a la clase tiene una referencia a una instancia de la clase, podría usar esa referencia como un objeto de bloqueo para un bloque completamente diferente del nuestro, protegiendo datos SyncLock diferentes. De esta manera, la clase y la otra clase podrían bloquearse entre sí para que no ejecuten sus bloques no SyncLock relacionados. De forma similar, el bloqueo en una cadena puede ser problemático, ya que cualquier otro código del proceso que use la misma cadena compartirá el mismo bloqueo.
Tampoco debe usar el método Me.GetType para proporcionar un objeto de bloqueo para los datos compartidos. Esto se debe a GetType que siempre devuelve el mismo objeto para un nombre de clase Type determinado. El código externo podría GetType llamar a en la clase y obtener el mismo objeto de bloqueo que está usando. Esto daría lugar a que las dos clases se bloquearan entre sí de sus SyncLock bloques.
Ejemplos
Descripción
En el ejemplo siguiente se muestra una clase que mantiene una lista simple de mensajes. Contiene los mensajes de una matriz y el último elemento usado de esa matriz en una variable. El addAnotherMessage procedimiento incrementa el último elemento y almacena el nuevo mensaje. Esas dos operaciones están protegidas por las instrucciones y , porque una vez que se ha incrementado el último elemento, el nuevo mensaje debe almacenarse antes de que cualquier otro subproceso pueda volver a incrementar el SyncLock End SyncLock último elemento.
Si la clase comparte una lista de mensajes entre todas sus instancias, las variables y simpleMessageList messagesList se messagesLast declararían como Shared . En este caso, la variable también debe ser , para que cada instancia utilice un único objeto de messagesLock Shared bloqueo.
Código
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
Descripción
En el ejemplo siguiente se usan subprocesos y SyncLock . Siempre que la SyncLock instrucción esté presente, el bloque de instrucciones es una sección crítica y nunca se convierte en un número balance negativo. Puede comentar las instrucciones SyncLock y para ver el efecto de dejar fuera la palabra clave End SyncLock SyncLock .
Código
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