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

Multithreading Discussion :

Problème de mutex [Protection de données]


Sujet :

Multithreading

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    198
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 198
    Par défaut Problème de mutex
    Bonjour,

    Je lance plusieurs threads en parallèle qui travaillent à partir d'une liste. Cette liste est protégée par un QMutex, mais malgré cela mes quatre threads traitent la même première occurrence et ne vident pas la liste.

    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
    class Thread : public QThread
    {
    	Q_OBJECT
    public:
    	Thread(QStringList&, int);
     
     
    protected:
    	void run();
     
    private:
    	QStringList Liste;
    	int num_thread;
    	volatile bool stopped;
    	QMutex mutexListe;
    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
    21
    22
    Thread::Thread(QStringList & list, int i)
    {
      stopped = false;
      Liste = list;
      num_thread = i;
    }
     
    void Thread::run()
    {
    	qDebug() << "Thread " << num_thread;
     
      forever {
        mutexListe.lock();
        int nb;
        if (!Liste.isEmpty()) {
           QString jobname(Liste.first());
           Liste.removeFirst();
           nb = Liste.size();
           mutexListe.unlock();
           //Mon code QProcess
           qDebug() << "Taille liste = " << nb << "  sur " << num_thread;
           qDebug() << "Lancement " << jobname << " sur " << num_thread;
    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
    21
     #include <QApplication>
     
     #include "Thread.h"
     
     int main(int argc, char *argv[])
     {
         QApplication app(argc, argv);
     
      int noeuds(4);
      QStringList Liste;
      Liste << "SCD1LoadDimSSKsFromDimAndFact" << "SCD1LoadFactSSKs" << "SCD1LoadTargetTable" << "SCD1Lookups1" << "SCD1Lookups10" << "SCD1Lookups2";
     
      for (int i(0) ; i < noeuds ; ++i)
      {
      	Thread * un_thread;
      	un_thread = new Thread(Liste, i);
      	un_thread->start();
      }  
     
      return 0;
     }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Thread  0
    Thread  1
    Thread  3
    Thread  2
    Taille liste =  5   sur  0
    Taille liste =  5   sur  1
    Taille liste =  5   sur  2
    Taille liste =  5   sur  3
    Lancement  "SCD1LoadDimSSKsFromDimAndFact"  sur  0
    Lancement  "SCD1LoadDimSSKsFromDimAndFact"  sur  2
    Lancement  "SCD1LoadDimSSKsFromDimAndFact"  sur  1
    Lancement  "SCD1LoadDimSSKsFromDimAndFact"  sur  3

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 6
    Par défaut
    je n'ai jamais fait de multi process....
    mais
    a priori le mutex empeche plusieurs threads de passer dans le même code.
    Or ici tu as une instance de mutex pour chaque thread, donc le lock ne concerne que le thread en question....

    Le mutex devrait être mis dans un objet encapsulant ta liste....
    les modifications de valeurs seraient alors effectuées par un thread en même temps

    à vérifier bien sûr

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    198
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 198
    Par défaut
    J'ai mis le mutex dans les données membres du thread comme c'est fait dans le livre Qt4 et C++.
    J'ai essayé en mettant le mutex en variable globales mais j'ai une erreur à la compilation.

  4. #4
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    507
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Mai 2006
    Messages : 507
    Par défaut
    Bonjour,

    democrie a raison, mutexListe étant une variable de classe non statique, il en existe autant que d'instance de la classe... donc ton mutex ne sert à rien.

    Pour que ce soit correct, il faut mettre mutexListe en static...

    Si ça ne compile toujours pas, montre les erreurs...

  5. #5
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par Fabllot Voir le message
    Bonjour,

    democrie a raison, mutexListe étant une variable de classe non statique, il en existe autant que d'instance de la classe... donc ton mutex ne sert à rien.

    Pour que ce soit correct, il faut mettre mutexListe en static...
    C'est une solution.
    Par contre,il fait la même erreur avec la liste. Chaque thread à sa propre liste....

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    198
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 198
    Par défaut
    Si je mets mutexListe en static j'ai l'erreur de compilation suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    g++ -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-rel
    oc -Wl,-subsystem,console -mthreads -Wl -o debug\QThread.exe debug/main.o debug/
    Thread.o debug/moc_Thread.o  -L"c:\Qt\qt\lib" -lQtGuid4 -lQtCored4
    debug/Thread.o(.text+0x542): In function `ZN6Thread3runEv':
    L:/CPP/Qt/QThread/Thread.cpp:18: undefined reference to `Thread::mutexListe'
    debug/Thread.o(.text+0x5b6):L:/CPP/Qt/QThread/Thread.cpp:24: undefined reference
     to `Thread::mutexListe'
    debug/Thread.o(.text+0x1035):L:/CPP/Qt/QThread/Thread.cpp:40: undefined referenc
    e to `Thread::mutexListe'
    collect2: ld returned 1 exit status
    mingw32-make[1]: *** [debug\QThread.exe] Error 1
    mingw32-make[1]: Leaving directory `L:/CPP/Qt/QThread'
    mingw32-make: *** [debug] Error 2
    Pourquoi chaque thread aurait sa liste puisque je passe laliste par référence au constructeur ?

  7. #7
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    507
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Mai 2006
    Messages : 507
    Par défaut
    Citation Envoyé par DSGSLA Voir le message
    Pourquoi chaque thread aurait sa liste puisque je passe la liste par référence au constructeur ?
    Parce que tu fais cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Thread::Thread(QStringList & list, int i)
    {
      // [...]
      Liste = list;
      // [...]
    }
    Et là, tu fais une copie de la liste... tu ne manipule pas des pointeurs. Ici le '&' indique que 'list' est une référence (donc les modifications faites dans la fonction sont impactées hors de la fonction), mais l'opérateur '=' copie réellement la liste (ie. la clone)... Donc tu te retrouves bien avec une liste différente pour chaque thread...

    Une éventuelle solution serait d'utiliser un pointeur de list...

    Et peux-tu poster ton code quand le mutex est en 'static' ?

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    198
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 198
    Par défaut
    Voici mon code avec le mutex en static et la liste en pointeur.
    Mais maintenant le programme plante. Je ne suis pas sûr de l'écriture de l'initialisation de la liste .

    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
    class Thread : public QThread
    {
    	Q_OBJECT
    public:
    	Thread(QStringList *, int);
     
     
    protected:
    	void run();
     
    private:
    	QStringList * Liste;
    	int num_thread;
    	volatile bool stopped;
    	static QMutex mutexListe;
    	QMutex mutexStdOut;
    	QMutex mutexStdErr;
    };
    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    Thread::Thread(QStringList * list, int i)
    {
      stopped = false;
      Liste = list;
      num_thread = i;
    }
     
    void Thread::run()
    {
    	qDebug() << "Thread " << num_thread;
     
      forever {
        mutexListe.lock();
        int nb;
        if (!Liste->isEmpty()) {
           QString jobname(Liste->first());
           Liste->removeFirst();
           nb = Liste->size();
           mutexListe.unlock();
     
           //Mon code QProcess
           qDebug() << "Taille liste = " << nb << "  sur " << num_thread;
           qDebug() << "Lancement " << jobname << " sur " << num_thread;
     
        }
        else {
              mutexListe.unlock();
              break;
        }
      }
    }
    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
     int main(int argc, char *argv[])
     {
         QApplication app(argc, argv);
     
      int noeuds(4);
      QStringList * Liste;
      *Liste << "SCD1LoadDimSSKsFromDimAndFact" << "SCD1LoadFactSSKs" << "SCD1LoadTargetTable" << "SCD1Lookups1" << "SCD1Lookups10" << "SCD1Lookups2";
     
      for (int i(0) ; i < noeuds ; ++i)
      {
      	Thread * un_thread;
      	un_thread = new Thread(Liste, i);
      	un_thread->start();
      }  
     
      return 0;
     }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    g++ -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-rel
    oc -Wl,-subsystem,console -mthreads -Wl -o debug\QThread.exe debug/main.o debug/
    Thread.o debug/moc_Thread.o  -L"c:\Qt\qt\lib" -lQtGuid4 -lQtCored4
    debug/Thread.o(.text+0x442): In function `ZN6Thread3runEv':
    L:/CPP/Qt/QThread/Thread.cpp:18: undefined reference to `Thread::mutexListe'
    debug/Thread.o(.text+0x4b6):L:/CPP/Qt/QThread/Thread.cpp:24: undefined reference
     to `Thread::mutexListe'
    debug/Thread.o(.text+0xf87):L:/CPP/Qt/QThread/Thread.cpp:43: undefined reference
     to `Thread::mutexListe'
    collect2: ld returned 1 exit status
    mingw32-make[1]: *** [debug\QThread.exe] Error 1
    mingw32-make[1]: Leaving directory `L:/CPP/Qt/QThread'
    mingw32-make: *** [debug] Error 2

  9. #9
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    507
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Mai 2006
    Messages : 507
    Par défaut
    Pour l'erreur de compilation, il manque dans le fichier Thread.cpp la ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    QMutex Thread::mutexList;
    Pour l'erreur d'exécution dans le programme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     QStringList * Liste;
      *Liste << "SCD1LoadDimSSKsFromDimAndFact" << "SCD1LoadFactSSKs" /* [...] */;
    Ce code plante car le pointeur Liste ne pointe nulle part...
    Il faut donc faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    QStringList * Liste = new QStringList ();
    pour que ça ne plante plus...

    Sinon petite remarque, il ne manquerait pas un bout de code avant le return 0 du main ?
    Il y a un risque que ton programme s'arrête avant que les threads se soient terminés et il n'y a aucune libération de mémoire, alors qu'il y a quelques new...

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    198
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 198
    Par défaut
    Citation Envoyé par Fabllot Voir le message
    Pour l'erreur de compilation, il manque dans le fichier Thread.cpp la ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    QMutex Thread::mutexList;
    Je ne vois pas où le placer et je ne comprends pas vraiment la notation et l'utilité.


    Citation Envoyé par Fabllot Voir le message
    Sinon petite remarque, il ne manquerait pas un bout de code avant le return 0 du main ?
    Il y a un risque que ton programme s'arrête avant que les threads se soient terminés et il n'y a aucune libération de mémoire, alors qu'il y a quelques new...
    Je dois faire un Thread.wait() c'est ça ?
    Dans les exemples de code je n'ai pas vu de delete pour les QThreads.

  11. #11
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    507
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Mai 2006
    Messages : 507
    Par défaut
    Citation Envoyé par DSGSLA Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    QMutex Thread::mutexList;
    Je ne vois pas où le placer et je ne comprends pas vraiment la notation et l'utilité.
    Quand tu définis une variable de classe en statique. Dans le fichier .h tu auras la déclaration de la variable. En gros tu informes juste le système que tu vas avoir une variable statique... Mais cette variable statique, comme tout autre variable il faut l'initialiser. Pour une variable de classe "classique", sa déclaration (ie son initialisation) se fait de manière implicite dans le constructeur de la classe. Cependant, une variable statique est unique pour toutes les instances d'une même classe, donc sa déclaration (ie son initialisation) ne peut se faire dans le constructeur... Il faut donc la faire ailleurs...

    Par exemple, dans ton fichier Thread.cpp:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    #include "Thread.h"
     
    QMutex Thread::mutexList; // sous-entendu "= QMutex ()"
     
    Thread::Thread(QStringList * list, int i) {
      stopped = false;
      Liste = list;
      num_thread = i;
    }
     
    // [...]

    Je dois faire un Thread.wait() c'est ça ?
    Dans les exemples de code je n'ai pas vu de delete pour les QThreads.
    Tu peux faire un wait, c'est une bonne idée. Pour le delete ce n'est pas une question de QThread ou non, c'est une question de pointeurs...
    En C++, quand tu fais un new sur une variable tu dois faire un delete.
    En C++/Qt, tu peux ne pas faire de delete que si dans le constructeur de la classe, tu lui as passer un objet parent... (Cf. http://qt.developpez.com/faq/?page=qt4Core#newdelete)

    Tu peux donc modifier ton main ainsi
    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
    21
    22
    23
    24
    25
    26
    27
    28
     
    int main(int argc, char *argv[]) {
       QApplication app(argc, argv);
       QStringList list;
       list << "SCD1LoadDimSSKsFromDimAndFact" << "SCD1LoadFactSSKs" 
          << "SCD1LoadTargetTable" << "SCD1Lookups1" 
          << "SCD1Lookups10" << "SCD1Lookups2";
     
       int noeuds = 4;
       QList <Thread*> threadList;
     
       // Création et lancement des threads
       for (int i=0; i<noeuds; ++i) {
          Thread* pThread = new Thread (&Liste, i);
          pThread->start();
          threadList << pThread;
       }  
     
       // Attente de la fin des threads et destructions
       while (threadList.count () > 0) {
          threadList[0]->wait ();
          delete threadList[i];
          threadList.removeFirst ();
       } 
     
       delete list;
       return 0;
    }

  12. #12
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    198
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 198
    Par défaut
    Tout fonctionne. Merci Fabllot.

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

Discussions similaires

  1. Problème de Mutex
    Par sinfoni dans le forum API, COM et SDKs
    Réponses: 4
    Dernier message: 07/12/2010, 18h09
  2. Problème de mutex en mode release
    Par fredppp dans le forum C++/CLI
    Réponses: 3
    Dernier message: 05/11/2010, 20h26
  3. problème de mutex et de condition
    Par mitmat dans le forum SDL
    Réponses: 4
    Dernier message: 03/04/2008, 17h25
  4. problème de mutex
    Par ep31 dans le forum MFC
    Réponses: 2
    Dernier message: 07/04/2006, 11h28
  5. Problème de mutex avec Waitforsingleobject non-bloquant
    Par rvzip64 dans le forum API, COM et SDKs
    Réponses: 6
    Dernier message: 03/11/2005, 11h02

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