En d'autres termes, ce thread d'implémentation Singleton est-il sûr:
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
la source
la source
Instance
à la fois. L'un des threads sera invité à exécuter d'abord l'initialiseur de type (également connu sous le nom de constructeur statique). Pendant ce temps, tous les autres threads souhaitant lire laInstance
propriété seront verrouillés jusqu'à la fin de l'initialiseur de type. Ce n'est qu'après la fin de l'initialisation du champ que les threads seront autorisés à obtenir laInstance
valeur. Donc, personne ne peut voir l'Instance
êtrenull
.X
finissent par être-1
même sans thread . Ce n'est pas un problème de sécurité des threads. Au lieu de cela, l'initialiseurx = -1
s'exécute en premier (il se trouve sur une ligne antérieure du code, un numéro de ligne inférieur). L'initialiseurX = GetX()
s'exécute ensuite, ce qui rend les majusculesX
égales à-1
. Et puis le constructeur statique "explicite", l'initialiseur de typestatic C() { ... }
s'exécute, qui ne change que les minusculesx
. Donc après tout cela, laMain
méthode (ou laOther
méthode) peut continuer et lire en majusculesX
. Sa valeur sera-1
, même avec un seul thread.Réponses:
Les constructeurs statiques sont garantis pour être exécutés une seule fois par domaine d'application, avant la création de toute instance d'une classe ou l'accès à des membres statiques. https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/static-constructors
L'implémentation indiquée est thread-safe pour la construction initiale, c'est-à-dire qu'aucun verrouillage ou test nul n'est requis pour construire l'objet Singleton. Cependant, cela ne signifie pas que toute utilisation de l'instance sera synchronisée. Il existe différentes façons de procéder; J'en ai montré un ci-dessous.
la source
Lazy<T>
- toute personne qui utilise le code que j'ai publié à l'origine le fait mal (et honnêtement, ce n'était pas si bon au début - il y a 5 ans), je n'étais pas aussi bon dans ce domaine que l'actuel -moi, ce est :) ).Bien que toutes ces réponses donnent la même réponse générale, il y a une mise en garde.
N'oubliez pas que toutes les dérivations potentielles d'une classe générique sont compilées en tant que types individuels. Soyez donc prudent lorsque vous implémentez des constructeurs statiques pour les types génériques.
ÉDITER:
Voici la démonstration:
Dans la console:
la source
L'utilisation d'un constructeur statique est en fait threadsafe. Le constructeur statique ne peut être exécuté qu'une seule fois.
De la spécification du langage C # :
Alors oui, vous pouvez être sûr que votre singleton sera correctement instancié.
Zooba a fait valoir un excellent point (et 15 secondes avant moi aussi!) Que le constructeur statique ne garantira pas un accès partagé thread-safe au singleton. Cela devra être traité d'une autre manière.
la source
Voici la version Cliffnotes de la page MSDN ci-dessus sur c # singleton:
Utilisez toujours le modèle suivant, vous ne pouvez pas vous tromper:
Au-delà des fonctionnalités évidentes de singleton, il vous offre ces deux choses gratuitement (en ce qui concerne singleton en c ++):
la source
Les constructeurs statiques sont garantis de se déclencher une seule fois par domaine d'application, votre approche doit donc être correcte. Cependant, elle n'est fonctionnellement pas différente de la version en ligne plus concise:
La sécurité des threads est plus un problème lorsque vous initialisez des choses paresseusement.
la source
Le constructeur statique terminera son exécution avant qu'un thread ne soit autorisé à accéder à la classe.
Le code ci-dessus a produit les résultats ci-dessous.
Même si l'exécution du constructeur statique a pris du temps, les autres threads se sont arrêtés et ont attendu. Tous les threads lisent la valeur de _x définie en bas du constructeur statique.
la source
La spécification Common Language Infrastructure garantit qu '"un initialiseur de type doit s'exécuter exactement une fois pour tout type donné, sauf s'il est explicitement appelé par le code utilisateur". (Section 9.5.3.1.) Donc, à moins que vous ayez un IL fou sur l'appel libre Singleton ::. Cctor directement (peu probable), votre constructeur statique s'exécutera exactement une fois avant l'utilisation du type Singleton, une seule instance de Singleton sera créée, et votre propriété d'instance est thread-safe.
Notez que si le constructeur de Singleton accède à la propriété Instance (même indirectement), la propriété Instance sera null. Le mieux que vous puissiez faire est de détecter quand cela se produit et de lever une exception, en vérifiant que l'instance n'est pas nulle dans l'accesseur de propriété. Une fois votre constructeur statique terminé, la propriété Instance sera non nulle.
Comme le souligne la réponse de Zoomba, vous devrez sécuriser Singleton pour accéder à partir de plusieurs threads, ou implémenter un mécanisme de verrouillage autour de l'utilisation de l'instance singleton.
la source
Juste pour être pédant, mais il n'y a pas de constructeur statique, mais plutôt des initialiseurs de type statique, voici une petite démonstration de la dépendance cyclique du constructeur statique qui illustre ce point.
la source
Le constructeur statique est garanti pour être thread-safe. Consultez également la discussion sur Singleton sur DeveloperZen: http://web.archive.org/web/20160404231134/http://www.developerzen.com/2007/07/15/whats-wrong-with-this-code -1-discussion /
la source
Bien que d'autres réponses soient pour la plupart correctes, il y a encore une autre mise en garde avec les constructeurs statiques.
Conformément à la section II.10.5.3.3 Courses et blocages de l' infrastructure linguistique commune ECMA-335
Le code suivant entraîne un blocage
L'auteur original est Igor Ostrovsky, voir son article ici .
la source