Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

[HS] Design Patterns : Singleton

20 réponses
Avatar
Stephane Wirtel
Bonsoir,

J'aurais aimé avoir votre avis sur la question concernant
l'implémentation du Design Pattern "Singleton" dans le cas d'une
application multi-thread.

J'ai pû constater que Mr Douglas C. Schmidt proposait comme solution, le
fait d'employer le Double Checked Locking, mais en faisant une recherche
sur google, j'ai pû constater que des exemples donnaient des résultats
contradictoires concernant ce pattern.

Auriez-vous un conseil à me fournir afin d'implémenter une classe
Singleton qui puissent fonctionner dans un environnement multi-thread ?

Merci,

Stéphane WIRTEL.

10 réponses

1 2
Avatar
Jean-Marc Bourguet
Stephane Wirtel writes:

Auriez-vous un conseil à me fournir afin d'implémenter une classe Singleton
qui puissent fonctionner dans un environnement multi-thread ?


L'initialiser *avant* de passer en multi-thread si tu veux eviter les
locks.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Laurent Deniau
Stephane Wirtel wrote:
Bonsoir,

J'aurais aimé avoir votre avis sur la question concernant
l'implémentation du Design Pattern "Singleton" dans le cas d'une
application multi-thread.

J'ai pû constater que Mr Douglas C. Schmidt proposait comme solution, le
fait d'employer le Double Checked Locking, mais en faisant une recherche
sur google, j'ai pû constater que des exemples donnaient des résultats
contradictoires concernant ce pattern.

Auriez-vous un conseil à me fournir afin d'implémenter une classe
Singleton qui puissent fonctionner dans un environnement multi-thread ?


solutions:

- creer le singleton avant d'etre en multithread
- garantir l'execution unique en multithread (voir pthread_once)
- utiliser des locks (tres lent).

Le DCL ne marche pas de facon portable.

a+, ld.

Avatar
Arnaud Debaene
Stephane Wirtel wrote:
Bonsoir,

J'aurais aimé avoir votre avis sur la question concernant
l'implémentation du Design Pattern "Singleton" dans le cas d'une
application multi-thread.

J'ai pû constater que Mr Douglas C. Schmidt proposait comme solution,
le fait d'employer le Double Checked Locking, mais en faisant une
recherche sur google, j'ai pû constater que des exemples donnaient
des résultats contradictoires concernant ce pattern.

Auriez-vous un conseil à me fournir afin d'implémenter une classe
Singleton qui puissent fonctionner dans un environnement multi-thread
Le DCLP ne marche à priori que sur des processeurs ayant une cohérence forte

de cache (X86...). Si tu veux être générique et portable, utilises un lock
pour chaque appel à "GetInstance".

Arnaud

Avatar
Stephane Wirtel
Stephane Wirtel wrote:

Bonsoir,

J'aurais aimé avoir votre avis sur la question concernant
l'implémentation du Design Pattern "Singleton" dans le cas d'une
application multi-thread.

J'ai pû constater que Mr Douglas C. Schmidt proposait comme solution,
le fait d'employer le Double Checked Locking, mais en faisant une
recherche sur google, j'ai pû constater que des exemples donnaient
des résultats contradictoires concernant ce pattern.

Auriez-vous un conseil à me fournir afin d'implémenter une classe
Singleton qui puissent fonctionner dans un environnement multi-thread


Le DCLP ne marche à priori que sur des processeurs ayant une cohérence forte
de cache (X86...). Si tu veux être générique et portable, utilises un lock
pour chaque appel à "GetInstance".

Arnaud


Merci Arnaud,


Mais j'ai tout de même une question, le DCL emploit un "lock" (mutex) pour justement rendre cohérent l'accès au GetInstance ().
N'y a-t-il pas une incohérence dans le fait d'employer un lock pour chaque appel à GetInstance () ?

Pourrais-tu m'aider à mieux comprendre ?

Merci


Avatar
Jean-Marc Bourguet
Stephane Wirtel writes:

Pourrais-tu m'aider à mieux comprendre ?


Le DCL suppose que
- l'ecriture d'un pointeur est atomique (autrement dit on va lire
ou bien l'ancienne valeur -- nulle -- ou la nouvelle, pas un
melange des deux);
- si le pointeur vers le singleton n'est pas nul, la valeur pointee
est correcte (et donc avec cet anti-idiome il n'y a pas de
synchronisation dans ce cas la). Or les methodes de coherence de
cache ne garantissent generalement rien sur l'ordre dans lequel
sont visibles sur un autre processeur des ecritures a des
adresses differentes. (Ils garantissent que tous les processeurs
partageant une adresse verront les ecritures a cette adresse dans
le meme ordre).

Seules les methodes de synchronisation fortes peuvent resoudre le
premier probleme.

Le deuxieme peut l'etre aussi en mettant dans la branche else la
barriere memoire qui va bien (voir la liste de celles de ton
processeur, si c'est l'IA64 et que tu comprends toute les nuances,
fais-moi signe, j'ai des questions a te poser :-), c'est moins
couteuse qu'un mutex (qui comprennent une telle instruction).

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
kanze
Arnaud Debaene wrote:
Stephane Wirtel wrote:

J'aurais aimé avoir votre avis sur la question concernant
l'implémentation du Design Pattern "Singleton" dans le cas
d'une application multi-thread.

J'ai pû constater que Mr Douglas C. Schmidt proposait comme
solution, le fait d'employer le Double Checked Locking, mais
en faisant une recherche sur google, j'ai pû constater que
des exemples donnaient des résultats contradictoires
concernant ce pattern.

Auriez-vous un conseil à me fournir afin d'implémenter une
classe Singleton qui puissent fonctionner dans un
environnement multi-thread


Le DCLP ne marche à priori que sur des processeurs ayant une
cohérence forte de cache (X86...). Si tu veux être générique
et portable, utilises un lock pour chaque appel à
"GetInstance".


Le DCLP ne marche a priori pas. Un point, c'est tout. Tel qu'il
est implémenté dans ACE, il ne marche même pas sur le 80x86 le
plus primitif, avec un seul processeur. S'il donne l'air de
marcher, parfois, c'est parce que le compilateur n'optimise pas.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
kanze
Jean-Marc Bourguet wrote:
Stephane Wirtel writes:

Pourrais-tu m'aider à mieux comprendre ?


Le DCL suppose que
- l'ecriture d'un pointeur est atomique (autrement dit on
va lire ou bien l'ancienne valeur -- nulle -- ou la
nouvelle, pas un melange des deux);


Oui, mais dans la pratique, c'est rarement un problème (même
s'il y a des cas sur des Intel où ce n'est pas garanti).

- si le pointeur vers le singleton n'est pas nul, la valeur
pointee est correcte (et donc avec cet anti-idiome il n'y
a pas de synchronisation dans ce cas la). Or les methodes
de coherence de cache ne garantissent generalement rien
sur l'ordre dans lequel sont visibles sur un autre
processeur des ecritures a des adresses differentes. (Ils
garantissent que tous les processeurs partageant une
adresse verront les ecritures a cette adresse dans le
meme ordre).


C'est pire. Le DCL suppose que toutes les écritures dans le code
apparaissent à tous les processeurs dans l'ordre qu'il serait
exécuté par la machine abstraite de la norme C++. Chose qui
n'est garantie par personne, et qui n'est en fait pas
généralement le cas dès qu'on active l'optimisation du
compilateur.

Seules les methodes de synchronisation fortes peuvent resoudre
le premier probleme.

Le deuxieme peut l'etre aussi en mettant dans la branche else
la barriere memoire qui va bien (voir la liste de celles de
ton processeur, si c'est l'IA64 et que tu comprends toute les
nuances, fais-moi signe, j'ai des questions a te poser :-),
c'est moins couteuse qu'un mutex (qui comprennent une telle
instruction).


En fait, il faut garantir que toutes les écritures dans la
branche qui appelle le constructeur soient visible à tous les
threads avant qu'un thread voit une valeur non-null en entrée de
la fonction. Suite à des discussions assez poussées dans
certains forums, on tend à oublier que l'implémentation de base
échoue indépendamment des problèmes de synchronisation -- dans
la mesure où il n'y a rien qui dit autrement, un compilateur est
libre de changer l'ordre des écritures dans le constructeur de
l'objet, et l'écriture du pointeur. Du coup, un autre thread
voit le pointeur non-null avant que les écritures dans le
constructeur ont eu lieu.

Les considérations sur la synchronisation ne devient critique
que quand on essaie d'adresser à ce problème sans mettre le
premier test sous le contrôle d'un lock.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Jean-Marc Bourguet
Laurent Deniau writes:

Si c'est ce que tu cherches, je ne vois pas l'interet du test avec NULL


La possibilite d'utiliser le singleton dans l'initialisation de
variables statiques (donc a un moment ou ourInstance n'a
potentiellement pas encore ete initialisee).

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Laurent Deniau
Jean-Marc Bourguet wrote:
Laurent Deniau writes:


Si c'est ce que tu cherches, je ne vois pas l'interet du test avec NULL



La possibilite d'utiliser le singleton dans l'initialisation de
variables statiques (donc a un moment ou ourInstance n'a
potentiellement pas encore ete initialisee).


Ok. On peut reformuler:

class Singleton
{
public:
static Singleton& instance() ;

private:
Singleton() {}
} ;

Singleton& Singleton::instance()
{
static Singleton& myInstance = *new Singleton;
return myInstance;
}

a+, ld.


Avatar
Jean-Marc Bourguet
Laurent Deniau writes:

Jean-Marc Bourguet wrote:
Laurent Deniau writes:

Si c'est ce que tu cherches, je ne vois pas l'interet du test avec NULL
La possibilite d'utiliser le singleton dans l'initialisation de

variables statiques (donc a un moment ou ourInstance n'a
potentiellement pas encore ete initialisee).


Ok. On peut reformuler:

class Singleton
{
public:
static Singleton& instance() ;

private:
Singleton() {}
} ;

Singleton& Singleton::instance()
{
static Singleton& myInstance = *new Singleton;
return myInstance;
}


C'est ce que j'utilise (presque, je n'aime pas l'utilisation de la
reference, j'utilise donc un pointeur) J'utilise meme

Singleton& Singleton::instance()
{
static Singleton myInstance;
return myInstance;
}

quand je n'ai pas a choisir une classe derivee. Je ne sais pas
pourquoi James fait autre chose.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org



1 2