Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Adquiere un bloqueo exclusivo para un bloque de instrucciones antes de ejecutar el bloque.
Sintaxis
SyncLock lockobject
[ block ]
End SyncLock
Partes
lockobject
Obligatorio. 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.
Observaciones
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 no se ejecute ningún otro subproceso.
El uso más común de es proteger los datos de ser actualizados por más de SyncLock un subproceso simultáneamente. Si las instrucciones que manipulan los datos deben ir a la finalización sin interrupción, colóquelas 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 un
SyncLockbloque desde fuera del bloque.Bloquear valor del objeto. El valor de
lockobjectno puede serNothing. Debe crear el objeto lock antes de usarlo en unaSyncLockinstrucción .No se puede cambiar el valor de
lockobjectmientras se ejecuta unSyncLockbloque. 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
SyncLockinstrucción , evalúa lalockobjectexpresión y suspende la ejecución hasta que adquiere un bloqueo exclusivo en el objeto devuelto por la expresión. Cuando otro subproceso llega a laSyncLockinstrucción , no adquiere un bloqueo hasta que el primer subproceso ejecuta laEnd SyncLockinstrucción .Datos protegidos. Si
lockobjectes unaSharedvariable, el bloqueo exclusivo impide que un subproceso de cualquier instancia de la clase ejecute elSyncLockbloque mientras cualquier otro subproceso lo está ejecutando. Esto protege los datos que se comparten entre todas las instancias.Si
lockobjectes una variable de instancia (noShared), el bloqueo impide que un subproceso que se ejecute en la instancia actual ejecute elSyncLockbloque al mismo tiempo que otro subproceso de la misma instancia. Esto protege los datos mantenidos por la instancia individual.Adquisición y lanzamiento. Un
SyncLockbloque se comporta como unaTry...Finallyconstrucción en la que elTrybloque adquiere un bloqueo exclusivo ylockobjectelFinallybloque lo libera. Debido a esto, elSyncLockbloque garantiza la liberación del bloqueo, independientemente de cómo salga del bloque. Esto es cierto incluso en el caso de una excepción no controlada.Llamadas de marco. El
SyncLockbloque adquiere y libera el bloqueo exclusivo llamando a losEntermétodos yExitde laMonitorclase en el System.Threading espacio de nombres .
Prácticas de programación
La lockobject expresión siempre debe evaluarse como un objeto que pertenece exclusivamente a la clase . Debe declarar una Private variable de objeto para proteger los datos que pertenecen a la instancia actual o una Private Shared variable de objeto para proteger los datos comunes a todas las instancias.
No debe usar la Me palabra 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 SyncLock bloque completamente diferente del suyo, protegiendo datos diferentes. De este modo, la clase y la otra clase podrían impedir que se ejecuten sus bloques no relacionados SyncLock . Del mismo modo, 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 Me.GetType método para proporcionar un objeto de bloqueo para los datos compartidos. Esto se debe a que GetType siempre devuelve el mismo Type objeto para un nombre de clase determinado. El código externo podría llamar a GetType en la clase y obtener el mismo objeto de bloqueo que está usando. Esto provocaría que las dos clases se bloquearan entre sí desde sus SyncLock bloques.
Ejemplos
Descripción
En el ejemplo siguiente se muestra una clase que mantiene una lista sencilla 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 SyncLock instrucciones y End SyncLock , porque una vez que se ha incrementado el último elemento, el nuevo mensaje debe almacenarse antes de que cualquier otro subproceso pueda incrementar de nuevo el último elemento.
Si la simpleMessageList clase compartió una lista de mensajes entre todas sus instancias, las variables messagesList y messagesLast se declararían como Shared. En este caso, la variable messagesLock también debe ser Shared, por lo que habría un único objeto de bloqueo usado por cada instancia.
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 balance nunca se convierte en un número negativo. Puede comentar las SyncLock instrucciones y End SyncLock para ver el efecto de salir de la SyncLock palabra clave .
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