Comment créez-vous un singleton thread-safe en Java ?

Création d'un Singleton Thread-Safe en Java avec le Verrouillage Double-Vérifié

Le concept d'un singleton en Java est une classe qui ne peut avoir qu'une instance. Cette instance unique peut alors être utilisée dans d'autres parties de votre code sans avoir à créer une nouvelle Classe de l'objet. C'est particulièrement utile lorsque vous voulez une seule instance globale à travers toute votre application, comme un gestionnaire de configuration ou un pool de connexions de base de données.

La question soulève un problème important dans l'implémentation d'un singleton : la sécurité des threads. Si plusieurs threads essaient de créer une instance de la classe singleton en même temps, il est possible qu'ils obtiennent chacun une instance distincte - brisant ainsi le principe du singleton. Pour éviter cela, nous devons garantir que notre classe singleton est "thread-safe", c’est-à-dire qu'elle se comporte comme prévu lorsqu'elle est utilisée dans un environnement multithread.

La meilleure manière de créer un singleton thread-safe en Java est d'utiliser le modèle de verrouillage double-vérifié. Voici comment cela fonctionne:

public class Singleton {
    private static volatile Singleton instance;
    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

Dans ce code:

  • La méthode getInstance() vérifie d'abord si une instance du singleton a déjà été créée (if (instance == null)). Si c'est le cas, elle retourne simplement cette instance.
  • Si aucune instance n'a été créée, elle synchronise le bloc de code qui suit sur Singleton.class. Cela signifie que seul un thread à la fois peut exécuter ce bloc de code.
  • À l'intérieur du bloc synchronisé, elle vérifie à nouveau si une instance a été créée (if (instance == null)). C'est parce qu'un autre thread a pu créer une instance alors que le thread actuel attendait pour entrer dans le bloc synchronisé.
  • Si aucune instance n'a été créée, elle en crée une et l'affecte à instance.

Le mot-clé volatile est essentiel ici. Il assure que les changements apportés à instance sont immédiatement visibles par tous les autres threads. Sans volatile, il est possible qu'un autre thread voie instance comme nul même après qu'il a été initialisé.

Ainsi, le verrouillage Double-Vérifié garantit une sécurité totale en environnement multi-thread tout en minimisant le coût de synchronisation, puisque le bloc synchronisé n'est exécuté qu'au moment de la première initialisation.

Trouvez-vous cela utile?