Le "Double-checked locking Pattern" et le "Singleton pattern"
Vous êtes développeur Java vous aussi ? Vous vous demandez à quoi ressemble le pattern Singleton.
Il s'agit d'une classe capable de vous retourner une instance d'elle-même. Cela vous évite d'instancier inutilement des classes quand vous avez besoin d'elles, d'autant plus quand ces classes sont consommatrices de ressources pour s'initialiser.
Le mauvais pattern du Singleton
Par défaut, sans trop d'expérience, vous pouvez facilement développer un Singleton de la forme suivante :
class Singleton
{
private static Singleton instance;
private Singleton()
{
// .....
}
public static Singleton getInstance()
{
if (instance == null)
instance = new Singleton();
return instance;
}
}
Vous n'avez peut-être pas détecté les problématiques éventuelles que peut poser cette solution lorsque l'application est fortement sollicitée ...
La méthode getInstance() étant statique, il est donc très fortement conseillé d'utiliser une synchronisation sur le "instance=new Singleton()" pour éviter les problèmes d'accès concurrents à la ressource.
Le pattern "Double-checked locking"
Voici un exemple d'antipattern à ne pas utiliser sur un projet. Il s'appelle "Double-checked locking pattern" car il utilise un double contrôle de la nullité de l'instance via un "synchronized" sur le code.
public static Singleton getInstance()
{
if (instance == null)
{
synchronized(Singleton.class) {
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
Mais cette solution ne résout pas le problème de risque de concurrence d'accès, elle réduit juste fortement la probabilité que le problème de concurrence d'instanciation du Singleton et complexifie le code inutilement.
Le bon pattern du Singleton
Voici donc la solution proposée par IBM :
class Singleton
{
private static Singleton instance = new Singleton();
private Singleton()
{
//...
}
public static Singleton getInstance()
{
return instance;
}
}
Cette solution est vraiment très simple et profite du mécanisme synchrone du classloader pour initialiser l'instance de classe.
Ce pattern rend la lecture de code plus simple et limite les risques d'erreur de développement.