Java Singleton et de Synchronisation
Veuillez préciser ma question concernant Singleton et le Multithreading:
- Quelle est la meilleure façon de mettre en œuvre Singleton en Java, dans un multithread
de l'environnement? - Ce qui se passe lorsque plusieurs threads tentent d'accéder
getInstance()
méthode en même temps? - Pouvons-nous faire singleton
getInstance()
synchronized
? - Est la synchronisation vraiment nécessaire, lors de l'utilisation d'un Singleton de classes?
Vous devez vous connecter pour publier un commentaire.
Oui, c'est nécessaire. Il existe plusieurs méthodes que vous pouvez utiliser pour garantir la sécurité des threads avec initialisation:
Draconiennes de synchronisation:
Cette solution nécessite que chaque thread être synchronisé alors qu'en réalité, seuls les premiers ont besoin d'être.
Vérifiez la synchronisation:
Cette solution garantit que seuls les premiers filets qui essaient d'acquérir votre singleton avoir à passer par le processus d'acquisition de la serrure.
Initialisation sur Demande:
Cette solution tire parti de la Java du modèle de mémoire garanties sur initialisation de classe pour assurer la sécurité des threads. Chaque classe ne peut être chargée qu'une seule fois, et il va seulement être chargé lorsqu'il est nécessaire. Cela signifie que la première fois
getInstance
est appelé,InstanceHolder
sera chargé etinstance
sera créé, et puisque c'est contrôlée parClassLoader
s, aucune synchronisation supplémentaire n'est nécessaire.Draconian synchronization
etDouble check synchronization
getInstance()-méthode doit être statique!static
, mais il pourrait faire plus de sens si elles l'étaient. Amendé à la demande.wait
sur la serrure.static
intérieur de la classe, sinon il ne fonctionnera pas. Cela va générer un autre *.fichier de classe au moment de la compilation, et une classe de chargement de charge lorsque vous d'abord accéder à votre singleton.YourObject.class
. Il est toujours plus sûr d'utiliser un privé verrouillage de l'objet, car alors vous savez exactement quand et où le moniteur sera saisiInstanceHolder
doit être une classe à part?public class Foo { private static Foo f = new Foo(); public static Foo getInstance() {return f;}
Ce qui est mal à cela?r
n'est pas nécessaire pour l'exactitude. C'est juste une optimisation pour éviter l'accès de la volatilité de champ, car c'est beaucoup plus cher que de l'accès à une variable locale.Ce modèle fait un "thread-safe" paresseux-initialisation de l'instance sans explicite de la synchronisation!
Cela fonctionne, car il utilise le chargeur de classe pour faire le tout de la synchronisation pour vous pour gratuit: La classe
MySingleton.Loader
est d'abord accéder à l'intérieur de lagetInstance()
méthode, de sorte que leLoader
charges de classe quandgetInstance()
est appelé pour la première fois. En outre, le chargeur de classes garantit que tous initialisation statique est terminée avant que vous obtenez l'accès à la classe - qu'est ce qui vous donne du fil de sécurité.C'est comme de la magie.
C'est en fait très similaire à la enum modèle de Jhurtado, mais je trouve l'enum modèle un abus de l'enum concept (bien qu'il fonctionne)
static final MySingleton INSTANCE
?final
devrait être ajouté. Fait.Si vous travaillez dans un environnement multithread en Java et la nécessité de garantir à tous les threads accèdent à une seule instance d'une classe, vous pouvez utiliser un Enum. Cela aura l'avantage de vous aider à gérer la sérialisation.
et puis juste avoir votre threads de l'utilisation de votre instance comme:
Oui, vous avez besoin de faire
getInstance()
synchronisé. Si elle n'est pas là pourraient survenir une situation où de multiples instances de la classe peuvent être faites.Considérons le cas où vous avez deux threads appel
getInstance()
en même temps. Maintenant, imaginez T1 exécute juste après leinstance == null
vérifier, puis T2 s'exécute. À ce stade de l'instance n'est créée ou d'un ensemble, de sorte T2 va passer la vérification et de créer une instance. Maintenant, imaginez que l'exécution revient à T1. Maintenant, le singleton est créé, mais T1 a déjà fait le chèque! Il procédera à faire de nouveau l'objet! FairegetInstance()
synchronisé évite ce problème.Il y a quelques façons de faire de singletons thread-safe, mais en faisant
getInstance()
de synchronisation est probablement le plus simple.Enum singleton
La façon la plus simple à mettre en œuvre un Singleton qui est thread-safe est d'utiliser un Enum
Ce code fonctionne depuis l'introduction de l'Enum dans Java 1.5
Une Double vérification de verrouillage
Si vous voulez un code “classique” singleton qui fonctionne dans un environnement multithread (à partir de Java 1.5), vous devez utiliser celui-ci.
Ce n'est pas thread-safe avant de 1.5 du fait de la mise en œuvre de mot-clé volatile était différent.
En charge précoce Singleton (fonctionne même avant de Java 1.5)
Cette mise en œuvre instancie le singleton lorsque la classe est chargé et assure la sécurité des threads.
Vous pouvez également utiliser des bloc de code pour instancier l'instance à la classe de charge et de prévenir le thread des problèmes de synchronisation.
instance
finale 2. Vous devriez fairegetInstance()
statique.Reportez-vous à ce poste pour une meilleure façon de mettre en Singleton.
Ce qui est un moyen efficace de mettre en œuvre un pattern singleton en Java?
Il dépend de la façon dont vous avez mis en œuvre la méthode.Si vous utilisez une double verrouillage sans volatils variable, vous pouvez obtenir partiellement construit objet Singleton.
Reportez-vous à cette question pour plus de détails:
Pourquoi est volatile utilisée dans cet exemple de la double vérification de verrouillage
Pas nécessaire si vous mettez en œuvre le Singleton en dessous de moyens
Reportez-vous à cette question pour plus de détails
Java Modèle De Conception Singleton : Questions
Source : Efficace Java -> Item 2
Il suggère de l'utiliser, si vous êtes sûr que la classe sera toujours singleton.