Je suis tombé sur cet article pour expliquer pourquoi le paradigme du verrouillage à double vérification est rompu en Java. Le paradigme est-il valable pour .NET (en particulier C #), si les variables sont déclarées volatile
?
Réponses
Trop de publicités?Double-vérifier le verrouillage fonctionne maintenant en Java et C# (la Java du modèle de mémoire changé et c'est l'un des effets). Toutefois, vous devez le faire exactement de la droite. Si vous gâcher les choses, même légèrement, vous pourriez bien finir par perdre le fil de sécurité.
Comme d'autres réponses ont indiqué, si vous êtes à la mise en œuvre du pattern singleton il y a de bien meilleures façons de le faire. Personnellement, si je suis dans une situation où je dois choisir entre le double-vérifier le verrouillage et le "verrouillage de tous les temps" code que j'irais pour le verrouillage de tous les temps jusqu'à ce que j'avais obtenu la preuve que c'était à l'origine un goulot d'étranglement. Quand il s'agit de filetage, un simple et, évidemment-modèle correct vaut beaucoup.
.NET 4.0 a un nouveau type: Lazy<T>
qui élimine toute inquiétude quant à la mauvaise interprétation du modèle. Cela fait partie de la nouvelle bibliothèque de tâches parallèle.
Voir le Centre de développement MSDN Parallel Computing: http://msdn.microsoft.com/en-us/concurrency/default.aspx
En passant, il existe un backport (je crois qu’il n’est pas supporté) pour .NET 3.5 SP1 disponible ici .
La mise en œuvre de Singleton en C# parle de ce problème dans la troisième version.
Il dit:
Prise de la variable d'instance volatils pouvez le faire fonctionner, comme le ferait explicite barrière de mémoire les appels, bien que dans ce dernier cas, même les experts ne s'entendent pas exactement quels sont les obstacles nécessaires. J'ai tendance à essayer d'éviter les situations où les experts ne s'entendent pas ce qui est droit et ce qui est mal!
L'auteur semble sous-entendre que la double verrouillage est moins susceptibles de travailler que les autres stratégies et ne devraient donc pas être utilisés.
Notez qu'en Java (et très probablement aussi en .Net), le double contrôle du verrouillage pour l'initialisation du singleton est complètement inutile et cassé. Comme les classes ne sont pas initialisées avant leur première utilisation, l’initialisation paresseuse souhaitée est déjà réalisée.
private static Singleton instance = new Singleton();
À moins que votre classe Singleton ne contienne des éléments tels que des constantes accessibles avant la première utilisation d’une instance Singleton, c’est tout ce que vous avez à faire.
J'ai vérifié le verrouillage à double contrôle en utilisant un booléen (c'est-à-dire en utilisant une primitive pour éviter l'initialisation lente):
Le singleton utilisant boolean ne fonctionne pas. L'ordre des opérations tel qu'il apparaît entre les différents threads n'est garanti que si vous passez par une barrière de mémoire. En d'autres termes, comme vu d'un second thread,
created = true
peut être exécuté avantinstance= new Singleton();