Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Quando vários threads podem fazer chamadas para as propriedades e métodos de um único objeto, é fundamental que essas chamadas sejam sincronizadas. Caso contrário, um thread poderá interromper o que outro thread está fazendo e o objeto poderá ser deixado em um estado inválido. Uma classe cujos membros estão protegidos contra essas interrupções é chamada thread-safe.
.NET fornece várias estratégias para sincronizar o acesso a membros estáticos e de instância:
Regiões de código sincronizadas. Você pode usar o suporte de Monitor classe ou compilador para essa classe para sincronizar apenas o bloco de código que precisa dela, melhorando o desempenho.
Sincronização manual. Você pode usar os objetos de sincronização fornecidos pela biblioteca de classes .NET. Confira a visão geral das primitivas de sincronização, que inclui uma discussão sobre a Monitor classe.
Contextos sincronizados. Somente para aplicativos do .NET Framework, você pode usar SynchronizationAttribute para habilitar a sincronização simples e automática de objetos ContextBoundObject.
Classes de coleção no System.Collections.Concurrent namespace. Essas classes fornecem operações de adição e remoção sincronizadas internas. Para obter mais informações, consulte Thread-Safe Collections.
O common language runtime fornece um modelo de thread no qual as classes se enquadram em várias categorias que podem ser sincronizadas de várias maneiras diferentes, dependendo dos requisitos. A tabela a seguir mostra qual suporte de sincronização é fornecido para campos e métodos com uma determinada categoria de sincronização.
| Category | Campos globais | Campos estáticos | Métodos estáticos | Campos de instância | Métodos de instância | Blocos de código específicos |
|---|---|---|---|---|---|---|
| Sem sincronização | Não | Não | Não | Não | Não | Não |
| Contexto sincronizado | Não | Não | Não | Yes | Yes | Não |
| Regiões de código sincronizadas | Não | Não | Apenas se estiver marcado | Não | Somente se estiver marcado | Somente se estiver marcado |
| Sincronização manual | Manual | Manual | Manual | Manual | Manual | Manual |
Sem sincronização
Esse é o padrão para objetos. Qualquer thread pode acessar qualquer método ou campo a qualquer momento. Apenas um thread de cada vez deve acessar esses objetos.
Sincronização manual
A biblioteca de classes .NET fornece várias classes para sincronizar threads. Confira a visão geral dos primitivos de sincronização.
Regiões de código sincronizadas
Você pode usar a Monitor classe ou uma palavra-chave do compilador para sincronizar blocos de código, métodos de instância e métodos estáticos. Não há suporte para campos estáticos sincronizados.
Tanto Visual Basic quanto C# dão suporte à marcação de blocos de código com uma palavra-chave de linguagem específica, a lock instrução em C# ou a SyncLock instrução em Visual Basic. Quando o código é executado por um thread, uma tentativa é feita para adquirir o bloqueio. Se o bloqueio já foi adquirido por outro thread, o thread bloqueia até que o bloqueio fique disponível. Quando o thread sai do bloco de código sincronizado, o bloqueio é liberado, independentemente de como o thread sai do bloco.
Note
Em .NET 9 e C# 13 ou posterior, se o destino lock for uma instância dedicada de System.Threading.Lock, a instrução lock usa Lock.EnterScope() para criar uma região sincronizada.
O Visual Basic não oferece suporte a System.Threading.Lock em SyncLock, portanto continue usando SyncLock com um tipo de referência privada dedicado.
Se o alvo lock não for uma instância de Lock e, para todo uso de SyncLock, o compilador usará Monitor.Enter e Monitor.Exit. Devido a essa implementação, você ainda pode usar outros Monitor métodos na região sincronizada.
Você também pode decorar um método com um MethodImplAttribute com um valor de MethodImplOptions.Synchronized, que tem o mesmo efeito de usar Monitor ou uma das palavras-chave do compilador para bloquear todo o corpo do método.
Thread.Interrupt pode ser usado para interromper um thread fora das operações de bloqueio, como aguardar o acesso a uma região de código sincronizada. Thread.Interrupt também é usado para interromper threads de operações, como Thread.Sleep.
Important
Não bloqueie o tipo — ou seja, typeof(MyType) em C#, GetType(MyType) em Visual Basic ou MyType::typeid em C++ — para proteger static métodos (Sharedmétodos em Visual Basic). Em vez disso, use um objeto estático privado. Da mesma forma, não use this em C# (Meem Visual Basic) para bloquear métodos de instância. Em vez disso, use um objeto privado. Uma classe ou instância pode ser bloqueada por código diferente do seu, potencialmente causando deadlocks ou problemas de desempenho.
Suporte ao compilador
Tanto Visual Basic quanto C# dão suporte a uma palavra-chave de linguagem que usa Monitor.Enter e Monitor.Exit para bloquear o objeto. Visual Basic dá suporte à instrução SyncLock; O C# dá suporte à instrução lock.
Em ambos os casos, se ocorrer uma exceção no bloco de código, o bloqueio adquirido pelo lock ou SyncLock será liberado automaticamente. Os compiladores C# e Visual Basic emitem um bloco try/finally com Monitor.Enter no início do bloco try e Monitor.Exit no bloco finally. Se uma exceção for lançada dentro do bloco lock ou SyncLock, o manipulador finally será executado para permitir que você faça qualquer tarefa de limpeza.
Contexto sincronizado
Somente em aplicativos do .NET Framework, você pode usar o SynchronizationAttribute em qualquer ContextBoundObject para sincronizar todos os métodos e campos de instância. Todos os objetos no mesmo domínio de contexto compartilham o mesmo bloqueio. Vários threads têm permissão para acessar os métodos e campos, mas apenas um único thread é permitido ao mesmo tempo.