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

Threads & Processus C++ Discussion :

Eviter les deadlocks


Sujet :

Threads & Processus C++

  1. #1
    Membre expérimenté Avatar de Rewpparo
    Homme Profil pro
    Amateur
    Inscrit en
    Décembre 2005
    Messages
    170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Amateur

    Informations forums :
    Inscription : Décembre 2005
    Messages : 170
    Par défaut Eviter les deadlocks
    Bonjour !
    Je cherche a faire un graphe dans un environnement extrêmement multithreadé. Les nodes du graphe doivent pouvoir être liés, c'est a dire que les deux nodes du lien stockent un pointeur vers l'autre élément. Je veux le rendre thread safe dans le sens où n'importe quel thread peut appeler link() avec n'importe quelle instance. Plusieurs thread peuvent le faire en même temps.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    class A
    {
         A* m_link
         Mutex m_mutex;
    public:
         bool link(A* p_other)
         {
              //checks
              if(!p_other) return false; //No link to null pointer
              if(m_link) return false; //Already linked
              //Lock mutexes
              Lock l1(p_other->m_mutex);
              if(p_other->m_link) return false; //p_other already linked
              Lock l2(m_mutex);
              //Link
              m_link = p_other;
              p_other->m_link=this;
              return true;
         }
    };
    Avec cette implémentation cependant, je cours le risque de gros deadlocks. Je me demandais s'il existait une solution à ce problème, ou s'il s'agit d'un problème de design.

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 118
    Par défaut
    Et oui tout le problème d'enchainer 2 lock de mutexes :

    thread A
    1. lock m1
    2. lock m2

    thread B
    1. lock m2
    2. lock m1

    Tu peux t'en sortir avec des timed_lock ou des try_lock sur les second lock.

  3. #3
    Membre expérimenté Avatar de Rewpparo
    Homme Profil pro
    Amateur
    Inscrit en
    Décembre 2005
    Messages
    170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Amateur

    Informations forums :
    Inscription : Décembre 2005
    Messages : 170
    Par défaut
    J'y avais pensé, mais je pensais que ça ne faisait que décaler le problème.
    En cas d’échec du try, si je fais une boucle pour relâcher le premier mutex et recommencer, j'ai l'impression que dans des cas très rares cette boucle peut devenir bloquante. Et si ça arrive, bonjour le débug.
    As tu une expérience en prod de cette boucle ?
    Le multithread me fait un peu peur en fait, j'ai vraiment l'impression que tout peut me péter à la gueule, et je suis a la recherche de bonnes pratiques.

  4. #4
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    Citation Envoyé par Rewpparo Voir le message
    J'y avais pensé, mais je pensais que ça ne faisait que décaler le problème.
    En cas d’échec du try, si je fais une boucle pour relâcher le premier mutex et recommencer, j'ai l'impression que dans des cas très rares cette boucle peut devenir bloquante. Et si ça arrive, bonjour le débug.
    As tu une expérience en prod de cette boucle ?
    Le multithread me fait un peu peur en fait, j'ai vraiment l'impression que tout peut me péter à la gueule, et je suis a la recherche de bonnes pratiques.
    Avec des time aléatoires, ça finit inévitablement par se débloquer. Mais ça rend le programme non déterministe, ce qui est à éviter autant que possible.

    Par contre, je n’ai pas compris ta structure de données. A ça représente quoi exactement ? Parce que ça ne ressemble pas à un nœud… Un nœud aurait une liste de nœuds auxquels il est relié, pas un seul.

  5. #5
    Membre expérimenté Avatar de Rewpparo
    Homme Profil pro
    Amateur
    Inscrit en
    Décembre 2005
    Messages
    170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Amateur

    Informations forums :
    Inscription : Décembre 2005
    Messages : 170
    Par défaut
    C'est un graphe un peu particulier, chaque noeud dispose d'une liste de demi-liens, et relier ces demi liens créé une liaison entre les noeuds. C'est lié au gameplay d'un jeu vidéo.

    J'ai essayé avec des opérations atomiques, mais ça me laisse les liens dans un état incohérent par moments.
    Les timings aléatoires de mutex sont une bonne idée. Ce système est assez isolé, ça ne devrait pas trop faire boule de neige. Je vais tester comme ça.
    Est ce qu'un simple yield() pourrait faire l'affaire ? un truc du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    std::mutex mutex1, mutex2;
     
    mutex1.lock();
    while(!mutex2.try_lock())
    {
         mutex1.unlock();
         std::this_thread::yield();
         mutex1.lock();
    }
    Ca marcherait ?


    EDIT : Je viens de tomber sur std::lock, C'est moi ou c'est exactement ce que je recherche ?

  6. #6
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Je pense que std::lock peut répondre à ton problème. Une autre solution, meilleure ou pas (selon le nombre de nœuds, la fréquence à laquelle les liens sont tirés...), consisterait à avoir non pas un mutex par noeud, mais un mutex global pour l'ensemble du graphe.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  7. #7
    Membre expérimenté Avatar de Rewpparo
    Homme Profil pro
    Amateur
    Inscrit en
    Décembre 2005
    Messages
    170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Amateur

    Informations forums :
    Inscription : Décembre 2005
    Messages : 170
    Par défaut
    En fait je ne peux pas me servir partout de std::lock, car j'ai besoin que le premier mutex soit locké pour pouvoir accéder de manière sure au deuxième. J'ai testé le code présent dans mon post précédent, ça a l'air de tenir.

    Pour le mutex unique, ça ne colle pas dans le contexte actuel, car d'autres opérations vont s'effectuer en utilisant ces mutex, et j'ai besoin de profiter de plus de parallélisme que ça. Mais je garde en tête, c'est une bonne idée qui sera surement la solution a un autre problème a un moment ou a un autre.

    Existe t il de bons bouquins sur la programmation parallèle ? Anglais ou français peu importe, mais que ce soit pratique, avec des exemples d'algos.

Discussions similaires

  1. Eviter les warnings "unused parameter"
    Par Le Furet dans le forum C
    Réponses: 9
    Dernier message: 03/10/2005, 22h29
  2. Eviter les doublons
    Par cyrill.gremaud dans le forum ASP
    Réponses: 5
    Dernier message: 14/09/2005, 12h37
  3. Réponses: 4
    Dernier message: 13/08/2004, 18h39
  4. [langage] 2 fichier dans 1 en evitant les doublons
    Par remixxl dans le forum Langage
    Réponses: 6
    Dernier message: 26/07/2004, 17h05
  5. [C#] Comment eviter les boucles infinies ?
    Par Thomas Lebrun dans le forum C#
    Réponses: 12
    Dernier message: 09/06/2004, 00h04

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