OVH Cloud OVH Cloud

Question bete sur les singletons

7 réponses
Avatar
Kupee
Salut, je me demandais une chose :
souvent on écrit une classe singleton comme ca :
public class Test {
private static Test instance;

private Test() {}

public static Test getInstance() {
if (instance == null) instance = new Test();
return instance;
}
}

Ce qui peut poser des problèmes de synchronisation et tout.
Pourquoi ne l'écrit t'on pas comme ca ? Ca ne résoudrait pas les soucis
de synchro ?


public class Test {
private static Test instance = new Test();

private Test() {}

public static Test getInstance() {
return instance;
}
}

7 réponses

Avatar
vc.spam
Salut,

Perso je l'écris comme la deuxième... Vu que les initialisations
static se font au premier appel sur la class, je pense que ça
n'anticipe pas l'initialisation... Et effectivement, j'espère bien que
la JVM synchronise les initialisations de membres statics...

A+

Vincent
Avatar
Xavier Tarrago
C'est un pattern qui date du bon vieux temps. En C++, les static sont
construits au lancement du programme (ou chargement de dll) (enfin, je
crois, c'est des vieux souvenirs!!!).
L'objectif initial est de repousser la construction de l'instance au moment
ou on en a besoin. En java ou une classe est chargée quand on l'utilise,
c'est moins intéressant. Mais si il y a d'autres méthodes dans la classe qui
n'utilisent pas le singleton, elles provoquent quand même la construction du
singleton.

"Kupee" a écrit dans le message de
news:42b2776d$0$25693$
Salut, je me demandais une chose :
souvent on écrit une classe singleton comme ca :
public class Test {
private static Test instance;

private Test() {}

public static Test getInstance() {
if (instance == null) instance = new Test();
return instance;
}
}

Ce qui peut poser des problèmes de synchronisation et tout.
Pourquoi ne l'écrit t'on pas comme ca ? Ca ne résoudrait pas les soucis
de synchro ?


public class Test {
private static Test instance = new Test();

private Test() {}

public static Test getInstance() {
return instance;
}
}


Avatar
Kupee
Xavier Tarrago wrote:
C'est un pattern qui date du bon vieux temps. En C++, les static sont
construits au lancement du programme (ou chargement de dll) (enfin, je
crois, c'est des vieux souvenirs!!!).
L'objectif initial est de repousser la construction de l'instance au moment
ou on en a besoin. En java ou une classe est chargée quand on l'utilise,
c'est moins intéressant. Mais si il y a d'autres méthodes dans la classe qui
n'utilisent pas le singleton, elles provoquent quand même la construction du
singleton.


Merci, donc dans la plupart des cas la seconde forme est meilleure.
Parfait :)

Avatar
sam
Pour plus d'infos à ce sujet,
http://christophej.developpez.com/tutoriel/java/singleton/multithread/


"Kupee" a écrit dans le message de
news:42b281d0$0$25693$
Xavier Tarrago wrote:
C'est un pattern qui date du bon vieux temps. En C++, les static sont
construits au lancement du programme (ou chargement de dll) (enfin, je
crois, c'est des vieux souvenirs!!!).
L'objectif initial est de repousser la construction de l'instance au
moment


ou on en a besoin. En java ou une classe est chargée quand on l'utilise,
c'est moins intéressant. Mais si il y a d'autres méthodes dans la classe
qui


n'utilisent pas le singleton, elles provoquent quand même la
construction du


singleton.


Merci, donc dans la plupart des cas la seconde forme est meilleure.
Parfait :)



Avatar
Alain
version courte
la première solution pose de problème de synchro et ne marche donc pas
la deuxième est la seule qui marche avec le VM récente
rien d'autre quoi qu'on dise ne marche bien avec les JVM récente en
multi-thread.

tout est expliqué là
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html


version longue.

la première solution pose un problème de double initialisation
si plusieurs thread demandent le même singleton ensemnle (car possible
sur un serveur à très forte charge, ou au startup)

il faut donc synchronizer la méthode... mais alors la synchro ralentis
toute l'application si on utilise souvent ce singleton (cas typique,
si par exemple ca représente le modele centrale de l'appli, ou une
connexion)

une pattern en vogue a un moment ca a été le Double-Checked Locking

on teste sans synchro si le pointeur est null,
puis si ou on fait un test en synchronisant le bloc...
mais en fait avec les JVM récente le bloc synchronized ne fait pas
qu'une section critique. ca oblige aussi le JVM à mettre les variables
en mémoire... en effet la JVM peut pour optimiser ne pas stocker en
mémoire les données et tout garder en registres processeur...
Il peut exécuter du code dans les désordre...
ainsi parfois le pointeur est initialisé avec l'adresse mémoire avant
que le constructeur soit terminé... le synchronized
impose certaines règles pour que les choses semblent logiques...
mais sans synchronized c'est n'importe quoi..
en plus synchronized ne garanti des trucs qu'avec un autre synchronized...
si vous êtres dans une section non synchronized le compilateur est libre
d'exécuter du code non synchrnized avant que le synchronized soit terminé...

ce qui se passe c'est que le premier test non synchronisé retourne
n'importe quoi, et que parfois on crois que l'objet est initialisé
alors qu'il ne l'est pas... parfois c'est le contraire...

bref, la seule pattern rapide et qui marche sans crash c'est
1- initialiser l'instance static au chargement de la classe
(c'est garanti synchronized par la JVM sans avoir rien a faire)
2- retourner bêtement le pointeur dans le getInstance

en plus d'être rapide et fiable c'est simple et clair

il faut juste mettre un commentaire dans le code pour qu'un débutant
zélé ne pête
pas tout en mettant la pattern "lasy initialisation" avec éventuellement
"double checked locking"

une référence à
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
devrait le faire bien.

pour une fois que les meilleurs experts ont conclus à
- "interdit de faire compliqué"


Salut, je me demandais une chose :
souvent on écrit une classe singleton comme ca :
public class Test {
private static Test instance;

private Test() {}

public static Test getInstance() {
if (instance == null) instance = new Test();
return instance;
}
}

Ce qui peut poser des problèmes de synchronisation et tout.
Pourquoi ne l'écrit t'on pas comme ca ? Ca ne résoudrait pas les soucis
de synchro ?


public class Test {
private static Test instance = new Test();

private Test() {}

public static Test getInstance() {
return instance;
}
}


Avatar
Sébastien
Alain wrote:
la première solution pose un problème de double initialisation
si plusieurs thread demandent le même singleton ensemnle (car possible
sur un serveur à très forte charge, ou au startup)

il faut donc synchronizer la méthode... mais alors la synchro ralentis
toute l'application si on utilise souvent ce singleton (cas typique,
si par exemple ca représente le modele centrale de l'appli, ou une
connexion)


Il ne faut pas non plus exagérer. Ce n'est pas un bloc synchronized qui va ralentir ton
application... Sauf à l'appeler 100 fois toutes les ms, et encore.

Utiliser la seconde solution plutôt que la première (avec lock) ne change pas grand chose.

Par contre, le Double-Checked Locking est effectivement une fausse bonne idée.

Sébastien

Avatar
Alexandre Touret
Sébastien wrote:
Alain wrote:

la première solution pose un problème de double initialisation
si plusieurs thread demandent le même singleton ensemnle (car possible
sur un serveur à très forte charge, ou au startup)

il faut donc synchronizer la méthode... mais alors la synchro ralentis
toute l'application si on utilise souvent ce singleton (cas typique,
si par exemple ca représente le modele centrale de l'appli, ou une
connexion)



Il ne faut pas non plus exagérer. Ce n'est pas un bloc synchronized qui
va ralentir ton application... Sauf à l'appeler 100 fois toutes les ms,
et encore.

Utiliser la seconde solution plutôt que la première (avec lock) ne
change pas grand chose.

Par contre, le Double-Checked Locking est effectivement une fausse bonne
idée.

Sébastien
Tout a fait d accord!

Un autre lien sur jaav.sun.com qui reference quelques cas ou les
singletons ne sont pas vraiment des singletons
http://java.sun.com/developer/technicalArticles/Programming/singletons/

Alexandre