2010-11-02 15 views

Répondre

0

La réponse est, cela dépend. Est-ce que votre instance est modifiable ou immuable? Si instance contient un état modifiable, vous devez le déclarer volatile. La raison pour laquelle vous devez cela n'a rien à voir avec les objets partiellement construits comme le suggère @Vijay Mathew, mais plutôt avec la visibilité du fil. Les modifications apportées à l'état de votre instance singleton dans un thread ne seront pas nécessairement visibles par un autre thread. L'utilisation du mot clé volatile garantit que le matériel utilisera un mécanisme pour vider le cache afin d'éliminer les données obsolètes.

La simultanéité Java en pratique, chapitre 16.2.3, décrit les idiomes d'initialisation sécurisés et contient un idiome d'initialisation paresseux. 16.2.4 traite de l'idiome de verrouillage par double vérification.

+0

La solution 'volatile' ne fonctionne que pour J2SE5 et plus. La solution la plus portable (c'est-à-dire sur plusieurs versions de la JVM) consiste toujours à utiliser une classe statique pour effectuer l'initialisation. –

2

Ce thread n'est pas sécurisé. L'instruction new Object(); n'est pas une opération atomique. instance cesse d'être null lorsque la mémoire lui est allouée. Un nouveau thread qui arrive à la première condition if après que la mémoire est allouée pour instance, mais avant que son constructeur est appelé renverra un objet partiellement construit. Si vous essayez d'implémenter un singleton thread-safe, utilisez Bill Pugh's solution qui est à la fois thread-safe et paresseux.

+0

-1: Votre déclaration concernant le fonctionnement de 'new' et l'affectation des variables est incorrecte. –

+0

Je ne suis pas un expert Java, mais je crois que la déclaration de Vijay est correcte. 'instance' peut certainement être affecté ** avant ** le constructeur est exécuté selon le modèle de mémoire de Java. Et, bien sûr, il ne peut pas être atomique car un nombre quelconque d'opérations pourrait être effectué dans le constructeur. –

+0

@Brian Gideon, je suis à peu près certain que Java suit toujours les règles de base pour l'évaluation d'expression même lors de la création de nouveaux objets. C'est-à-dire, pour '=' tout ce qui est à droite doit être évalué avant que l'opérateur puisse être évalué. Inclure, allouer de l'espace, initialiser des variables et exécuter le code du constructeur. http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html –

1

D'accord avec les messages précédents de Tim. Volatile fait de la visibilité et la raison pour laquelle le double contrôle de vérification a été décrit comme clever but broken concerne des objets partiellement construits (cohérence de cache/optimisations JVM). Tout est dans le livre de Goetz comme le suggère Tim, mais je voulais soulever un point autour de l'initialisation paresseuse. Pourquoi le faire? Dans mon expérience, ce n'est généralement pas nécessaire et vous vous trouvez dans un contexte multithread et vous êtes vraiment préoccupé par la sécurité de l'intialisation - vous avez introduit beaucoup de variabilité et de complexité qui est vraiment difficile à tester.

Je voudrais également souligner l'ancien avertissement de ne pas optimiser tôt. Savez-vous que la synchronisation grossière ralentit l'application? Habituellement, c'est la contention des verrous qui est lente, pas le mot-clé syncrhonization per-sa. Un test rapide avec syncrhonized et DCL confirmerait.