IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Design Patterns Discussion :

singleton et multithreading [Singleton]


Sujet :

Design Patterns

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    255
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 255
    Points : 99
    Points
    99
    Par défaut singleton et multithreading
    Le singleton est-il compatible avec le multithreading ?

    Le fait que l'instance du singleton soit partageable entre plusieurs thread fait que ses données peuvent être modifiées par plusieurs threads simultanément...

    En fait j'imagine que cette question ramène à toute classe qui met à disposition des données directement ou indirectement statiques (indirectement : ici une instance est accessible statiquement).

    Habituellement on doit protéger les données qui peuvent être modifiées par plusieurs threads.

    Doit-on alors prévoir pour tout singleton une protection similaire afin d'être "MultithreadSafe" ?

  2. #2
    Membre averti
    Inscrit en
    Mai 2006
    Messages
    423
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 423
    Points : 303
    Points
    303
    Par défaut
    Bonjour,
    pour protéger ton singleton tu peut lui associer un attribut booléen :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    classe singleton {
      privé booleen verou;
    }
    Suivant la valeur de cet attribut tu permet l'accès au singleton ou non.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    methode get_instance(){
      ....
      SI(this.verou){
        insérer demande dans liste d'attente;
      }
      SINON{
        retourner objet
      }
    }
    
    methode set_verrou(valeur){
      this.verou = valeur;
    }

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    255
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 255
    Points : 99
    Points
    99
    Par défaut
    ta reponse est donc oui ? pour la methode je prefererais utiliser les outils de synchronisation du langage !

  4. #4
    ego
    ego est déconnecté
    Rédacteur

    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Juillet 2004
    Messages
    1 883
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 883
    Points : 3 510
    Points
    3 510
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par behess Voir le message
    Le singleton est-il compatible avec le multithreading ?

    Le fait que l'instance du singleton soit partageable entre plusieurs thread fait que ses données peuvent être modifiées par plusieurs threads simultanément...

    En fait j'imagine que cette question ramène à toute classe qui met à disposition des données directement ou indirectement statiques (indirectement : ici une instance est accessible statiquement).

    Habituellement on doit protéger les données qui peuvent être modifiées par plusieurs threads.

    Doit-on alors prévoir pour tout singleton une protection similaire afin d'être "MultithreadSafe" ?
    2 autres solutions "mieux"...je pense :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public Class MySingleton {
      private static MySingleton instance;
    
      static {
          instance = new MySingleton ();
      }
    
      public static MySingleton getInstance() { return instance; }
    }
    L'autre solution est d'utiliser Spring !

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    255
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 255
    Points : 99
    Points
    99
    Par défaut
    Oui c'est une solution classique pour un singleton.

    Mais ce que je recherche c'est à bloquer cet appel à getInstance() tant qu'un autre thread UTILISE cette même instance.

    C'est à dire tant qu'une référence à cette instance existe en dehors du Singleton.

    J'ai pensé aux références faibles mais je ne vois pas trop comment faire, ça à l'air ardu.

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    255
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 255
    Points : 99
    Points
    99
    Par défaut
    Citation Envoyé par mehdiing Voir le message
    Bonjour,
    pour protéger ton singleton tu peut lui associer un attribut booléen :

    [...]
    Voici une implémentation en C# de cette idée ; ça ajoute juste une méthode de release de l'instance, ça pourrait peut-être aller.

    Le soucis principal c'est que si l'utilisateur du singleton fait simplement instanceRef=null ou même s'il n'appelle pas la méthode Release, le singleton reste verrouillé... il faut donc bien faire attention.

    J'aurai aimé quelque chose de plus systématique... mais cela semble impossible !

  7. #7
    Membre éprouvé
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Points : 1 066
    Points
    1 066
    Par défaut
    Citation Envoyé par ego Voir le message
    2 autres solutions "mieux"...je pense :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public Class MySingleton {
      private static MySingleton instance;
    
      static {
          instance = new MySingleton ();
      }
    
      public static MySingleton getInstance() { return instance; }
    }
    Ce qui est dommage avec cette solution, c'est qu'on perd le lazy instantiation.

    Personnellement, je préfère cette méthode:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class Singleton {
        private static Singleton instance = null;
    
        public static synchronized Singleton getInstance() {
            if(instance == null)
                instance = new Singleton();
            
            return instance;
        }
    }
    On pourrait me rétorquer qu'on perd des performances si deux élements veulent l'obtenir en même temps, mais... sincèrement, la perte n'est pas extraordinaire.

    Après, bien entendu, il est important de synchroniser les accès aux méthodes et attributs de ce singleton. Mais oui, le singleton peut être utilisé en multithread.
    Si tu tiens absolument à bloquer l'objet tant qu'il n'est pas relaché, tu peux rajouter une méthode getLock dessus, qui retournerait un ReentrantLock assigné à cette instance. Tu peux alors locker l'instance et la relacher quand tu n'en as plus besoin. Mais là tu risques de perdre du temps à l'exécution.
    Il vaut mieux synchroniser seulement ce qui en a besoin.

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    255
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 255
    Points : 99
    Points
    99
    Par défaut
    Oui en fait c'est stupide, autant synchroniser toutes les méthodes d'instance... c'est carrément plus simple ! Mdr.

    Que je suis con parfois.

  9. #9
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Bonsoir
    Une autre solution pour éviter les pbs de synchro d'appel a get_instance peut être de créer le singleton avant le lancement des threads applicatives.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  10. #10
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    255
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 255
    Points : 99
    Points
    99
    Par défaut
    ça aussi c'est pas con...

  11. #11
    Membre éprouvé
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Points : 1 066
    Points
    1 066
    Par défaut
    Le créer c'est bien, mais il faut s'assurer après que les différentes threads ne mettent pas un désordre général dans les attributs et autres.
    Il faut donc de toute façon synchroniser certaines méthodes.

  12. #12
    ego
    ego est déconnecté
    Rédacteur

    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Juillet 2004
    Messages
    1 883
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 883
    Points : 3 510
    Points
    3 510
    Billets dans le blog
    2
    Par défaut
    La meilleur solution est de se reporter au framework Sping.
    Mais bon, le pb du Monsieur est donc plutôt de synchronizer les opérations du singleton ? N'est-ce pas ça que tu veux ?
    Le mot synchronized sur les opérations de la classe !
    Ou alors j'ai pas tout compris

  13. #13
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    255
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 255
    Points : 99
    Points
    99
    Par défaut
    Oui la question était théorique.

    En fait il y a deux pb avec le Singleton en Multithreading :

    - la création
    - l'accès aux méthodes d'instance

    Et la réponse est évidemment : pour éviter les problèmes d'accès en multithreading il faut donc toujours mettre en place la synchronisation des différentes méthodes d'instance d'un Singleton.

    (sauf si on est ABSOLUMENT sûr que jamais le Singleton ne sera utilisé par plusieurs thread)

    Tout simplement.

  14. #14
    Membre éprouvé
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Points : 1 066
    Points
    1 066
    Par défaut
    Hola, pas trop de zèle :p Le synchronized peut, d'une part, faire perdre beaucoup de performances si on synchronise trop; et d'autre part peut même créer des deadlocks dans certains cas. Ca arrive notamment dans certains cas d'associations many to many.

  15. #15
    ego
    ego est déconnecté
    Rédacteur

    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Juillet 2004
    Messages
    1 883
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 883
    Points : 3 510
    Points
    3 510
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Antoine_935 Voir le message
    Hola, pas trop de zèle :p Le synchronized peut, d'une part, faire perdre beaucoup de performances si on synchronise trop; et d'autre part peut même créer des deadlocks dans certains cas. Ca arrive notamment dans certains cas d'associations many to many.
    many-to-many ?
    Mais le singleton est généralement utiliser pour des classes "Traitements" ou des "dictionnaires", non ?

  16. #16
    Membre éprouvé
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Points : 1 066
    Points
    1 066
    Par défaut
    Euh, oula, oui, c'est juste.
    De tte façon, il est par définition impossible de faire une many to many avec un singleton...

    M'enfin tout ça pour dire que le synchronized partout n'est pas une bonne idée. (ouf, je me rattrappe aux racines tant qu'il y en a )

  17. #17
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Bonsoir,

    Citation Envoyé par Antoine_935 Voir le message
    M'enfin tout ça pour dire que le synchronized partout n'est pas une bonne idée. (ouf, je me rattrappe aux racines tant qu'il y en a )
    Synchronized encapsule la méthode dans une section critique: un seul thread pourra exécuter le code à l'instant t et si d'autres threads appellent la méthode, elles attendent...

    Sans en mettre partout, il est quand même nécessaire d'en mettre parfois... La section critique étant là pour rendre 'atomique' la modification (écriture) de certaines données dites "partagées" ou globales.

    Ce vers quoi il faut tendre c'est de réduire la durée de traitement "dans la section critique" voire réduire à zéro les sections critiques présentant des problèmes de contention avec une implémentation ad hoc.

    Ceci dit, pour réduire les phénomène de contention - et les soucis de "scalabilité" de l'application qu'ils induisent - on peut limiter le nombre de threads:
    - 1 thread par (par exemple) session posera peu de problèmes de contention avec 2-10 threads ordonnancées sur un seul CPU
    - pourra en poser beaucoup plus lorsqu'il y aura plus de processeurs - et de threads actives....
    - deviendra catastrophique avec plein de threads 'actives' et encore plus de processeurs.

    Pour faire en sorte que le nombre de threads soit 'constant' (ne dépendant que du nombre de processeurs disponibles), il faut sortir le contexte d'exécution en le transformant en requêtes traitées par une ou plusieurs threads.

    => Dans ce cas, on remplace l'ordonnanceur 'système' qui gérait les nombreuses threads par un ordonnanceur 'cousu' main qui sera dépendant du temps de traitement moyen de chaque requête.

    Tout çà pour dire que tirer profit de pleins de CPU dans un environnement multi-threads peut devenir rapidement 'compliqué'. Livrer une première version d'un code sans trop de bugs en utilisant un framework qui permettre d'avoir un minimum de scalabilité sans avoir a se préoccuper de tout ces soucis est quand même sympa.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  18. #18
    Membre éprouvé
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Points : 1 066
    Points
    1 066
    Par défaut
    Citation Envoyé par Antoine_935 Voir le message
    Ce qui est dommage avec cette solution, c'est qu'on perd le lazy instantiation.
    Vous souvenez vous de cette réponse que j'ai posté plus haut ?
    Eh bien, après un des cours d'ajourd'hui, je réalise que je me suis planté, en partie du moins. La suite devrait être sufisamment explicite.

    Class: Main.java
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    public class Main {
        public static void main(String[] args) {
            System.out.println("Entered main function");
            Loading.getInstance();
        }
    }
    Class: Loading.java
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class Loading {
        private static Loading instance;
    
        static {
            System.out.println("Now creating the instance");
            instance = new Loading();
        }
    
        public static Loading getInstance() {
            return instance;
        }
    }
    Resultat:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Entered main function
    Now creating the instance
    Cela est du au fait que Java fait lui-même de la lazy instantiation pour les classes. Loading ne sera pas chargé avant qu'on n'en ait besoin.

    Autrement dit, si la seule méthode statique de Loading est getInstance, alors on peut se servir du clinit, tout en conservant le côté lazy.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Singleton et multithreading
    Par alladdin dans le forum Langage
    Réponses: 8
    Dernier message: 29/07/2010, 23h31
  2. Singleton et multithread
    Par totoche dans le forum Servlets/JSP
    Réponses: 2
    Dernier message: 25/05/2010, 18h05
  3. Singleton et Multithreading
    Par behess dans le forum C#
    Réponses: 22
    Dernier message: 09/09/2009, 11h09
  4. Singleton et multithreading
    Par Alp dans le forum C++
    Réponses: 17
    Dernier message: 06/08/2006, 02h49

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo