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 :

VS2010: Main thread bloqué ?


Sujet :

Threads & Processus C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Avatar de Mikmacer
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2006
    Messages
    116
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2006
    Messages : 116
    Par défaut VS2010: Main thread bloqué ?
    Salut!

    Je suis vraiment bloqué sur un problème présentement, qui n'arrive qu'en mode release avec visual studio 2010 sur windows(ça fonctionne en mode debug par contre).

    Je programme une application temps réel, je crée un thread par processeur logique. Le problème arrive lorsque je démarre mon premier thread(Autre que le "main thread"), le main thread boucle sur une variable bool avec un while. la variable bool devient true lorsque le nouveau thread entre dans sa fonction de départ.

    Le problème, c'est que le processus du main thread arrive à la condition, et il arrête de s'exécuter pour aucune raison, il ne boucle plus, il est mort. J'ai compilé avec gcc sur linux en release/debug, ça fonctionne, sur windows VS2010 ça fonctionne en debug, mais en release le processus reste idle pour aucune raison.

    Je dis que le main thread reste bloqué, parce que j'ai ajouté les infos de debug a l'exécutable, et que j'ai vérifié en pesant sur le bouton pause, et le processus ne sort jamais de la ligne! Même que je ne peux pas déplacer la flèche d'exécution ailleur dans la boucle. De plsu la variable a la valeur true, et le nouveau thread continue, lui, son exécution.

    Voici la boucle:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    while (true)
    {
     
    	bool val = CURRENT_DEDICATED_TASK->Entered;
    	if (val) // Le main thread bloque ICI
    		break;
    }
    Par contre, si j'envois quelque chose dans la console, le processus ne bloque pas, et il continue de boucler jusqu'à ce que la valeur soit vrai:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    while (true)
    {
    	bool val = CURRENT_DEDICATED_TASK->isEntered();
    	if (val)
    		break;
    	// Fonctione!!
    	std::cout << "Allo";
    }
    Je n'ai aucune idée de ce qui arrive, j'aimerais comprendre le problème!

    Merci pour votre aide.

  2. #2
    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
    C'est normal, le compilateur a tout à fait le droit de voir que tu ne modifies jamais CURRENT_DEDICATED_TASK->Entered dans ta boucle, et donc d'en tenir compte pour optimiser.

    Dès que de la mémoire doit être lue par plusieurs threads, elle doit être protégée (par des sémaphores, des mutex, des sections critiques, des opérations atomiques...). Cette protection a deux effets :
    - Elle empêche des race conditions à proprement parler
    - Elle interdit au compilateur de faire certaines optimisations qu'il est en droit de faire autrement
    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.

  3. #3
    Membre éprouvé
    Avatar de Mikmacer
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2006
    Messages
    116
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2006
    Messages : 116
    Par défaut
    Merci pour l'infos, je pensais pas que le compilateur faisait ces optimisations. J'ai mis la variable volatile, et ça fonctionne maintenant.

  4. #4
    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
    Attention, c'est volontairement que je n'ai pas mis volatile dans les liste des manières d'éviter ça. Il se peut que ça marche avec ton compilateur, dans certaines configurations, mais le comportement n'est aps garanti dans le cas général.

    Volatile est destiné à de la mémoire modifiée directement par un périphérique sans accéder au processeur. Pas à de la synchro entre threads. Je crois qu'en pratique, sur une configuration à plusieurs cœurs, la différence peut être très sensible !
    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.

  5. #5
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    Comme Loic : volatile c'est pour indiquer au compilo qu'une variable peut changer sans qu'il puisse le déterminer. L'exemple classique, c'est en développement embarqué où tu utilises volatile pour une variable adressant un périphérique. volatile pour du multithread c'est erroné.

    Tu peux utiliser une condition pour savoir dans main si le thread a démarré (remplacer thd par boost ou std selon que tu utilises boost ou les threads C++0x) :
    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
    thd::condition_variable the_condition;
    thd::mutex the_mutex;
     
    void second_thread()
    {
        the_condition.notify_one();
     
        // blablabla
    }
     
     
    int main()
    {
        thd::thread new_one(second_thread);
     
        thd::unique_lock<thd::mutex> the_lock(the_mutex);
        the_condition.wait(the_lock);
     
        //
     
        return 0;
    }
    Pour une synchronisation plus forte entre les 2 threads, avec boost.thread, tu peux t'appuyer sur les barrières :
    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
    thd::barrier the_barrier(2);
     
    void second_thread()
    {
        the_barrier.wait();
     
        // blablabla
    }
     
     
    int main()
    {
        thd::thread new_one(second_thread);
        the_barrier.wait();
     
        //
     
        return 0;
    }

  6. #6
    Membre éprouvé
    Avatar de Mikmacer
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2006
    Messages
    116
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2006
    Messages : 116
    Par défaut
    En fait, je me basais sur la définition de volatile en .NET où "Les champs qui sont déclarés volatile ne sont pas soumis aux optimisations du compilateur qui supposent l'accès par un seul thread.". Par contre, ça ne semble pas être la même pour C++(Interprété différement pour chacun des compilateurs.)

    Les conditions/barrier semblent intéressant! Malheuresement j'essais de me départir de boost pour certaines raisons. J'utilise tinythread++ comme alternative multiplateforme, et il ne contient que des mutex. Je vais finalement utiliser un mutex lock/unlock sur la booléenne pour que le compilateur évite l'optimisation de la lecture de la variable.

    Merci pour les précisions.

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

Discussions similaires

  1. [QThread] Main thread qui bloque un autre thread
    Par Amnell dans le forum Multithreading
    Réponses: 6
    Dernier message: 25/02/2010, 15h38
  2. ne signaler qu'un seul thread bloqué
    Par Joeamined dans le forum Threads & Processus
    Réponses: 1
    Dernier message: 10/11/2007, 11h34
  3. [Thread ] Thread bloqué
    Par lykim1982 dans le forum Visual C++
    Réponses: 1
    Dernier message: 07/06/2007, 16h38
  4. [API Win32 sans MFC] Lecture port série: thread bloqué
    Par dacid dans le forum Bibliothèques
    Réponses: 2
    Dernier message: 24/05/2006, 13h34
  5. [Threads et interface] le thread bloque tout
    Par meda dans le forum Concurrence et multi-thread
    Réponses: 10
    Dernier message: 28/10/2004, 16h52

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