Lock Classe
Definição
Importante
Algumas informações se referem a produtos de pré-lançamento que podem ser substancialmente modificados antes do lançamento. A Microsoft não oferece garantias, expressas ou implícitas, das informações aqui fornecidas.
Observação
Para usar essa API de visualização, você precisará habilitar recursos de visualização no seu projeto definindo a propriedade EnablePreviewFeatures
como True
no arquivo do projeto. Para obter mais informações, confira https://aka.ms/dotnet-preview-features.
Fornece um mecanismo para alcançar a exclusão mútua em regiões de código entre threads diferentes.
public ref class Lock sealed
[System.Runtime.Versioning.RequiresPreviewFeatures]
public sealed class Lock
[<System.Runtime.Versioning.RequiresPreviewFeatures>]
type Lock = class
Public NotInheritable Class Lock
- Herança
-
Lock
- Atributos
Comentários
A Lock classe pode ser usada para definir regiões de código que exigem acesso mutuamente exclusivo entre threads de um processo, comumente chamado de seções críticas, para impedir acessos simultâneos a um recurso. Um Lock
pode ser inserido e encerrado, em que a região do código entre a entrada e a saída é uma seção crítica associada ao bloqueio. Um thread que entra em um bloqueio é dito para manter ou possuir o bloqueio até que ele saia do bloqueio. No máximo, um thread pode manter um bloqueio a qualquer momento. Um thread pode conter vários bloqueios. Um thread pode inserir um bloqueio várias vezes antes de sair dele, como recursivamente. Um thread que não pode inserir um bloqueio imediatamente pode aguardar até que o bloqueio possa ser inserido ou até que um tempo limite especificado expire.
Ao usar os Enter métodos ou TryEnter para inserir um bloqueio:
- Verifique se o thread sai do bloqueio com Exit mesmo em caso de exceções, como em C# usando um
try/finally
bloco. - Quando o bloqueio estiver sendo inserido e encerrado em um método C#
async
, verifique se não há nenhumawait
entre a entrada e a saída. Os bloqueios são mantidos por threads e o código após umawait
pode ser executado em um thread diferente.
É recomendável usar o EnterScope método com um constructo de linguagem que descarta automaticamente o retornadoLock.Scope, como o palavra-chave C# using
ou para usar o palavra-chave C# lock
, pois eles garantem que o bloqueio seja encerrado em casos excepcionais. Esses padrões também podem ter benefícios de desempenho ao usar Enter/TryEnter
e Exit
. O fragmento de código a seguir ilustra vários padrões para inserir e sair de um bloqueio.
public sealed class ExampleDataStructure
{
private readonly Lock _lockObj = new();
public void Modify()
{
lock (_lockObj)
{
// Critical section associated with _lockObj
}
using (_lockObj.EnterScope())
{
// Critical section associated with _lockObj
}
_lockObj.Enter();
try
{
// Critical section associated with _lockObj
}
finally { _lockObj.Exit(); }
if (_lockObj.TryEnter())
{
try
{
// Critical section associated with _lockObj
}
finally { _lockObj.Exit(); }
}
}
}
Ao usar o palavra-chave C# lock
ou semelhante para inserir e sair de um bloqueio, o tipo da expressão deve ser precisamente System.Threading.Lock
. Se o tipo da expressão for qualquer outra coisa, como Object
ou um tipo genérico como T
, uma implementação diferente que não seja intercambiável poderá ser usada em vez disso (como Monitor). Para obter mais informações, consulte o speclet do compilador relevante.
Interrupt pode interromper threads que estão aguardando para entrar em um bloqueio. Em threads do Windows STA, espera por bloqueios que permitem o bombeamento de mensagens que podem executar outro código no mesmo thread durante uma espera. Alguns recursos das esperas podem ser substituídos por um personalizado SynchronizationContext.
Observação
Um thread que entra em um bloqueio, incluindo várias vezes, como recursivamente, deve sair do bloqueio o mesmo número de vezes para sair totalmente do bloqueio e permitir que outros threads entrem no bloqueio. Se um thread for encerrado enquanto mantém um Lock
, o comportamento do Lock
se tornará indefinido.
Cuidado
Se, em um caminho de código, um thread pode inserir vários bloqueios antes de sair deles, verifique se todos os caminhos de código que podem inserir dois desses bloqueios no mesmo thread os inserirão na mesma ordem. Caso contrário, isso pode levar a deadlocks. Por exemplo, considere que, em um thread T1
de caminho de código, insira bloqueio L1
e bloqueio L2
antes de sair de ambos e, em outro thread T2
de caminho de código, insira ambos os bloqueios na ordem inversa. Nesse cenário, seria possível que a seguinte ordem de eventos ocorresse: T1
insere L1
, T2
entra L2
, T1
tenta entrar L2
e aguarda, T2
tenta entrar L1
e aguarda. Há um deadlock entre T1
e T2
que não pode ser resolvido, e qualquer outro thread que tentar entrar em qualquer bloqueio no futuro também será travado.
Construtores
Lock() |
Inicializa uma nova instância da classe Lock. |
Propriedades
IsHeldByCurrentThread |
Obtém um valor que indica se o bloqueio é mantido pelo thread atual. |
Métodos
Enter() |
Insere o bloqueio, aguardando, se necessário, até que o bloqueio possa ser inserido. |
EnterScope() |
Insere o bloqueio, aguardando, se necessário, até que o bloqueio possa ser inserido. |
Equals(Object) |
Determina se o objeto especificado é igual ao objeto atual. (Herdado de Object) |
Exit() |
Sai do bloqueio. |
GetHashCode() |
Serve como a função de hash padrão. (Herdado de Object) |
GetType() |
Obtém o Type da instância atual. (Herdado de Object) |
MemberwiseClone() |
Cria uma cópia superficial do Object atual. (Herdado de Object) |
ToString() |
Retorna uma cadeia de caracteres que representa o objeto atual. (Herdado de Object) |
TryEnter() |
Tenta entrar no bloqueio sem esperar. |
TryEnter(Int32) |
Tenta inserir o bloqueio, aguardando, se necessário, o número especificado de milissegundos até que o bloqueio possa ser inserido. |
TryEnter(TimeSpan) |
Tenta inserir o bloqueio, aguardando, se necessário, até que o bloqueio possa ser inserido ou até que o tempo limite especificado expire. |