Em outras palavras, esse segmento de implementação Singleton é seguro:
public class Singleton
{
private static Singleton instance;
private Singleton() { }
static Singleton()
{
instance = new Singleton();
}
public static Singleton Instance
{
get { return instance; }
}
}
c#
multithreading
singleton
urini
fonte
fonte
Instance
uma só vez. Um dos threads será instruído a executar primeiro o inicializador de tipo (também conhecido como construtor estático). Enquanto isso, todos os outros threads que desejam ler aInstance
propriedade serão bloqueados até que o inicializador de tipo termine. Somente após a conclusão do inicializador de campo, os segmentos poderão obter oInstance
valor. Então ninguém pode ver oInstance
sernull
.X
acabam sendo iguais,-1
sem o uso de threads . Não é um problema de segurança de threads. Em vez disso, o inicializadorx = -1
é executado primeiro (ele está em uma linha anterior do código, um número de linha inferior). Em seguida, o inicializadorX = GetX()
é executado, o que torna maiúsculaX
igual a-1
. E, em seguida, o construtor estático "explícito", o inicializador de tipostatic C() { ... }
é executado, que muda apenas em minúsculasx
. Então, depois de tudo isso, oMain
método (ouOther
método) pode continuar e ler maiúsculasX
. Seu valor será-1
, mesmo com apenas um segmento.Respostas:
É garantido que os construtores estáticos sejam executados apenas uma vez por domínio de aplicativo, antes de qualquer instância de uma classe ser criada ou qualquer membro estático ser acessado. https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/static-constructors
A implementação mostrada é segura para threads para a construção inicial, ou seja, nenhum teste de bloqueio ou nulo é necessário para a construção do objeto Singleton. No entanto, isso não significa que qualquer uso da instância será sincronizado. Existem várias maneiras de fazer isso; Eu mostrei um abaixo.
fonte
Lazy<T>
- qualquer um que use o código que eu postei originalmente está fazendo errado (e honestamente não era tão bom assim - para 5 anos atrás, eu não era tão bom nessas coisas quanto as atuais -eu é :) ).Embora todas essas respostas dêem a mesma resposta geral, há uma ressalva.
Lembre-se de que todas as derivações potenciais de uma classe genérica são compiladas como tipos individuais. Portanto, tenha cuidado ao implementar construtores estáticos para tipos genéricos.
EDITAR:
Aqui está a demonstração:
No console:
fonte
Usar um construtor estático é realmente seguro para threads. O construtor estático é garantido para ser executado apenas uma vez.
Na especificação da linguagem C # :
Então, sim, você pode confiar que seu singleton será instanciado corretamente.
Zooba fez um excelente argumento (e 15 segundos antes de mim também!) De que o construtor estático não garantirá o acesso compartilhado seguro por thread ao singleton. Isso precisará ser tratado de outra maneira.
fonte
Aqui está a versão Cliffnotes da página acima do MSDN em c # singleton:
Use o seguinte padrão, sempre, você não pode dar errado:
Além dos recursos óbvios do singleton, ele oferece essas duas coisas de graça (em relação ao singleton em c ++):
fonte
É garantido que os construtores estáticos são acionados apenas uma vez por domínio de aplicativo, portanto sua abordagem deve ser boa. No entanto, funcionalmente não é diferente da versão mais concisa e em linha:
A segurança do encadeamento é mais um problema quando você está inicializando preguiçosamente as coisas.
fonte
O construtor estático terminará a execução antes que qualquer thread possa acessar a classe.
O código acima produziu os resultados abaixo.
Embora o construtor estático tenha demorado muito para ser executado, os outros threads pararam e esperaram. Todos os threads lêem o valor de _x definido na parte inferior do construtor estático.
fonte
A especificação Common Language Infrastructure garante que "um inicializador de tipo seja executado exatamente uma vez para qualquer tipo, a menos que seja explicitamente chamado pelo código do usuário". (Seção 9.5.3.1.) Portanto, a menos que você tenha alguma IL louca na chamada solta Singleton ::. Cctor diretamente (improvável), seu construtor estático será executado exatamente uma vez antes que o tipo Singleton seja usado, apenas uma instância do Singleton será criada, e sua propriedade Instance é segura para threads.
Observe que, se o construtor de Singleton acessar a propriedade Instance (mesmo que indiretamente), a propriedade Instance será nula. O melhor que você pode fazer é detectar quando isso acontece e lançar uma exceção, verificando se a instância não é nula no acessador de propriedade. Após a conclusão do construtor estático, a propriedade Instance será não nula.
Como a resposta de Zoomba aponta, você precisará tornar o Singleton seguro para acessar a partir de vários threads ou implementar um mecanismo de bloqueio usando a instância singleton.
fonte
Só para ser pedante, mas não existe construtor estático, mas inicializadores de tipo estático, aqui está uma pequena demonstração da dependência cíclica do construtor estático que ilustra esse ponto.
fonte
O construtor estático é garantido como seguro para threads. Além disso, confira a discussão sobre Singleton no DeveloperZen: http://www.developerzen.com/2007/07/15/whats-wrong-with-this-code-1-discussion/
fonte
Embora outras respostas estejam na maior parte corretas, há ainda outra ressalva com os construtores estáticos.
De acordo com a seção II.10.5.3.3, corridas e impasses da infraestrutura de idioma comum ECMA-335
O código a seguir resulta em um conflito
O autor original é Igor Ostrovsky, veja seu post aqui .
fonte