Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Adquire um bloqueio exclusivo para um bloco de instrução antes de executar o bloco.
Sintaxe
SyncLock lockobject
[ block ]
End SyncLock
Partes
lockobject
Obrigatório Expressão que é avaliada como uma referência de objeto.
block
Opcional. Bloco de instruções que devem ser executadas quando o bloqueio é adquirido.
End SyncLock
Encerra um SyncLock bloco.
Observações
A SyncLock instrução garante que vários threads não executem o bloco de instrução ao mesmo tempo.
SyncLock impede que cada thread entre no bloco até que nenhum outro thread o esteja executando.
O uso mais comum é SyncLock proteger os dados de serem atualizados por mais de um thread simultaneamente. Se as instruções que manipulam os dados devem ser concluídas sem interrupção, coloque-as dentro de um SyncLock bloco.
Um bloco de instruções protegido por um bloqueio exclusivo às vezes é chamado de seção crítica.
Regras
Ramificação. Você não pode ramificar em um
SyncLockbloco de fora do bloco.Bloquear valor do objeto. O valor de
lockobjectnão pode serNothing. Você deve criar o objeto lock antes de usá-lo em umaSyncLockinstrução.Não é possível alterar o valor de durante a execução de
lockobjectumSyncLockbloco. O mecanismo requer que o objeto de bloqueio permaneça inalterado.Não é possível usar o operador Await em um
SyncLockbloco.
Comportamento
Mecanismo. Quando um thread atinge a
SyncLockinstrução, ele avalia a expressão e suspende alockobjectexecução até adquirir um bloqueio exclusivo no objeto retornado pela expressão. Quando outro thread atinge aSyncLockinstrução, ele não adquire um bloqueio até que o primeiro thread execute aEnd SyncLockinstrução.Dados protegidos. Se
lockobjectfor umaSharedvariável, o bloqueio exclusivo impede que um thread em qualquer instância da classe execute oSyncLockbloco enquanto qualquer outro thread o está executando. Isso protege os dados que são compartilhados entre todas as instâncias.Se
lockobjectfor uma variável de instância (nãoShared), o bloqueio impede que um thread em execução na instância atual execute oSyncLockbloco ao mesmo tempo que outro thread na mesma instância. Isso protege os dados mantidos pela instância individual.Aquisição e Liberação. Um
SyncLockbloco comporta-se como umaTry...Finallyconstrução em que oTrybloco adquire um bloqueio exclusivo elockobjectoFinallybloco liberta-o. Por causa disso, oSyncLockbloco garante a liberação do bloqueio, não importa como você saia do bloco. Isto é verdade mesmo no caso de uma exceção não tratada.Chamadas de estrutura. O
SyncLockbloco adquire e libera o bloqueio exclusivo chamando osEntermétodos eExitdaMonitorclasse no System.Threading namespace.
Práticas de programação
A lockobject expressão deve sempre avaliar um objeto que pertence exclusivamente à sua classe. Você deve declarar uma Private variável de objeto para proteger os dados pertencentes à instância atual ou uma Private Shared variável de objeto para proteger os dados comuns a todas as instâncias.
Você não deve usar a Me palavra-chave para fornecer um objeto de bloqueio para dados de instância. Se o código externo à sua classe tiver uma referência a uma instância da sua classe, ele poderá usar essa referência como um objeto de bloqueio para um SyncLock bloco completamente diferente do seu, protegendo dados diferentes. Dessa forma, sua classe e a outra classe podem bloquear uma à outra de executar seus blocos não relacionados SyncLock . Da mesma forma, bloquear uma cadeia de caracteres pode ser problemático, uma vez que qualquer outro código no processo usando a mesma cadeia de caracteres compartilhará o mesmo bloqueio.
Você também não deve usar o Me.GetType método para fornecer um objeto de bloqueio para dados compartilhados. Isso ocorre porque GetType sempre retorna o mesmo Type objeto para um determinado nome de classe. O código externo pode chamar GetType sua classe e obter o mesmo objeto de bloqueio que você está usando. Isso resultaria em que as duas classes se bloqueassem mutuamente de seus SyncLock blocos.
Exemplos
Descrição
O exemplo a seguir mostra uma classe que mantém uma lista simples de mensagens. Ele contém as mensagens em uma matriz e o último elemento usado dessa matriz em uma variável. O addAnotherMessage procedimento incrementa o último elemento e armazena a nova mensagem. Essas duas operações são protegidas pelas SyncLock instruções and End SyncLock , porque uma vez que o último elemento tenha sido incrementado, a nova mensagem deve ser armazenada antes que qualquer outro thread possa incrementar o último elemento novamente.
Se a simpleMessageList classe compartilhasse uma lista de mensagens entre todas as suas instâncias, as variáveis messagesList e messagesLast seriam declaradas como Shared. Neste caso, a variável messagesLock também deve ser Shared, para que haja um único objeto de bloqueio usado por cada instância.
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
Descrição
O exemplo a seguir usa threads e SyncLock. Enquanto a SyncLock declaração estiver presente, o bloco de declaração é uma seção crítica e balance nunca se torna um número negativo. Você pode comentar as SyncLock declarações e End SyncLock para ver o efeito de deixar de fora a SyncLock palavra-chave.
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