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

POSIX C Discussion :

Synchronisation et communication entre Thread


Sujet :

POSIX C

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2020
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2020
    Messages : 12
    Points : 8
    Points
    8
    Par défaut Synchronisation et communication entre Thread
    Bonjour;
    Je rencontre un problème lors d'une implémentation d'une communication entre threads.
    je souhaiterais faire communiquer un thread père ( ici le main) avec un thread fils. Lorsque le main crée un thread fils, il va attendre que le fils créé choisit une valeur aléatoire et qu'il lui renvoi via des pointeurs; il pourra alors à son tour choisir une valeur et l'envoyer également au fils.

    " Schéma" de la communication:
    fils créé;
    père attend la valeur du fils;
    fils choisit sa valeur, envoie un signal, et se met en attente;
    père reçoit le signal, choisi sa valeur, envoie un signal aussi fils

    Lorsque je compile le programme reste en attente, je pense que le problème vient du wait du fils car j'ai l'impression que le fils ne reçoit jamais le signal que lui envoie le père mais je ne comprends pas pourquoi. Avez- vous une idée d'où peut venir l'erreur?

    Merci d'avance

    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
     
    pthread_mutex_t mutx = PTHREAD_MUTEX_INITIALIZER;
    pthread_cond_t cndx = PTHREAD_COND_INITIALIZER;
     
     
    typedef struct {
     pthread_mutex_t * mut;
     pthread_cond_t * cnd;
     int i;
     int * val1;
     int *val2;
    } barriere_t;
     
     
    void * thread (void * a) {
     barriere_t * b = (barriere_t *) a;
     
     pthread_mutex_lock (b->mut);
     printf ("Entree pour le fils %d\n", b->i);
     *b->val1=rand()%20; //le fils choisi une valeur
     pthread_cond_signal (&cndx); //envoit un signal au pere pour dire qu'il a choisi une valeur
     pthread_cond_wait (b->cnd, b->mut);//attend que le pere fini de choisir
     printf ("La valeur choisi par le pere est   %d\n", *b->val2); //affiche la valeur du pere
     printf ("fin\n");
     pthread_mutex_unlock (b->mut);
     
     return NULL;
    }
     
    int main (){
     srand(time(NULL));
     int i;
     pthread_t tid [3];
     barriere_t bar [1];
     pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
     pthread_cond_t cnd = PTHREAD_COND_INITIALIZER;
     
     int * null = malloc (sizeof (int) );
     *null = -1;
     
     
     for (i = 0; i < 1; ++i) {
      pthread_mutex_lock (&mutx);
      //initialisation des variables
      bar [i] .mut = &mut;
      bar [i] .cnd = &cnd;
      bar [i] .val1 = null;
      bar [i] .val2 = null;
      bar [i] .i = i;
      pthread_create (tid + i, NULL, thread, bar + i);
     
      pthread_cond_wait (&cndx, &mutx);//attendre que le fils choisi une valeur
      printf ("La valeur choisi par le fils est   %d\n", *bar [i] .val1);
      *null = rand()%20;//le pere choisi une valeur
      bar [i] .val2 = null;
    pthread_cond_signal (bar [i] .cnd);//envoit un signal au fils pour l'informer
      pthread_mutex_unlock (&mutx);
     
     }
     
     
     for (i = 0; i < 1; ++i)
      pthread_join (tid [i], NULL);
     
     free (null);
    }

  2. #2
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 562
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 562
    Points : 7 628
    Points
    7 628
    Par défaut
    Bonjour,

    Tu n'as pas bien compris à quoi servent les mutex. Un mutex définit une zone utilisable que par un seul thread à la fois. Cela implique que :
    - pour être protégé d'un accès concurrentiel, deux threads doivent prendre le même mutex. Sinon ça protège de rien.
    - pour avoir un vrai traitement parallèle, il faut diminuer la zone protégé à sa taille la plus courte possible. Il ne faut donc surtout pas prendre un mutex sur tout le traitement, car cela revient à bloquer l'autre pendant tout le traitement, et donc pourquoi utiliser des threads si pendant qu'un tourne l'autre reste bêtement en attente de prise de mutex.
    Et tu n'appliques aucune de ces règles.

    Par contre, tu as bien compris que pendant la phase d'attente d'une variable conditionnelle, on doit indiquer le mutex à libérer pendant l'attente, et ça doit être celui qui protège la zone dans laquelle est l'attente.
    Tu as besoin de 2 variables conditionnelles (en as-tu vraiment deux distinctes, à vérifier?), et peut-être que 2 mutex de protection, là c'est peut-être un peu trop.

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2020
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2020
    Messages : 12
    Points : 8
    Points
    8
    Par défaut
    Bonjour,

    pour être protégé d'un accès concurrentiel, deux threads doivent prendre le même mutex. Sinon ça protège de rien.

    Je crois que je n'ai pas bien compris. Pour l'instant je n'essaye pas de gérer l’accès concurrentiel car le thread père ne va pas accéder à la fonction du fils. Et donc si j'ai bien compris il n'y aura pas d’accès concurrentiel. J'utilise les mutex uniquement pour pouvoir utiliser les conditions, et non pas pour la concurrence des threads.


    Tu as besoin de 2 variables conditionnelles (en as-tu vraiment deux distinctes, à vérifier?), et peut-être que 2 mutex de protection, là c'est peut-être un peu trop.

    Je n'ai utiliser que 2 variables conditionnelles qui sont :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    pthread_cond_t cndx = PTHREAD_COND_INITIALIZER; //pour le père 
    pthread_cond_t cnd = PTHREAD_COND_INITIALIZER; //pour le fils
    Et j'ai également utiliser deux mutex :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    pthread_mutex_t mutx = PTHREAD_MUTEX_INITIALIZER; //pour le père
     pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; //pour le fils

  4. #4
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 562
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 562
    Points : 7 628
    Points
    7 628
    Par défaut
    Bonjour,

    un mutex ça sert à gérer la concurrence des threads et à rien d'autre!
    Tu dis "J'utilise les mutex uniquement pour pouvoir utiliser les conditions" c'est vrai, mais si les cond_var en ont besoin c'est parce qu'elle sont justement en concurrence entre thread.
    Et justement tu dois utiliser le même mutex pour l'émission et la reception, sinon il ne sert à rien.
    Donc une solution "simple" c'est de n'avoir qu'un seul mutex, c'est ce que je préconisais pour que ça marche, mais tu peux travailler avec 2 mutex, c'est juste un peu plus 'subtil' sachant que si tu prends 2 mutex tu risques le "dead-lock".
    Et le mutex doit protéger les accès à une variable et mécanisme de signal associé.
    Donc on doit protéger le couple (*bar[i].val1 et cnd) par un mutex (donc tous ce qui les concernent doivent être protégée par un mutex, on est bien d'accord que ses 2 choses sont utilisées par les 2 threads sont sont en conflit potentiels d'accès), et on doit proteger le couple (*bar[i].val2 et cnd2) par un mutex qui peut être le même par exemple. Mais toujours toujours toujours, le mutex qui protège un couple dans un thread doit être le même qui protège le même couple dans n'importe quel autre thread.
    J'ajoute juste que bar[i].val1 == bar[i].val2 == null donc tes 2 variables *bar[i].val1 et *bar[i].val2 ont la même adresse et sont en fait une unique variable! Mais ça ne gène pas ton code actuel. L'erreur est dans la mauvaise utilisable des mutex.

    un mutex ça sert à gérer la concurrence des threads et à rien d'autre!

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2020
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2020
    Messages : 12
    Points : 8
    Points
    8
    Par défaut
    Bonsoir,
    je n'avais pas compris que l'utilisation des mutex dépendait des variables, je pensais que comme je n'avais que deux conditions il me fallait aussi deux mutex. Merci de m'avoir aidé à comprendre cela, car en utilisant un seul mutx mon code marche.

    Je rencontre actuellement un autre problème, serait-il possible de m'aider encore une fois?

    Alors voilà, maintenant j'essaye de créer plusieurs fils qui vont chacun effectuer plusieurs tirages aléatoires et le père répond a tour de orle. Lorsque je crée 5 fils par exemple et qui font chacun 4 tirages mon programme marche. Mais lorsque j'utilise des nombres plus grands (par exemple quand je crée 10 fils qui font 100 tirages) je rencontre le même problème que le premier programme c'est-à-dire que mon programme reste en attente. J'ai utilisé un seul mutex, et j'ai essayé de diminuer la partie protégée par le mutex.

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 113
    Points : 32 958
    Points
    32 958
    Billets dans le blog
    4
    Par défaut
    Quand ton programme se bloque, fais une pause dans le debugger et regarde où il se trouve/ce qu'il se passe.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  7. #7
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 562
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 562
    Points : 7 628
    Points
    7 628
    Par défaut
    Bonjour,

    Je vois que tu as bien doublé les variables. Tu as donc maintenant 2 variables, mais c'est maintenant 11 threads qui doivent se les partager!
    Essayons de compter les éléments qui s'échangent dans ton code :
    - 11 threads
    - 10 structures permettant les échanges entre un thread et le thread principal. Jusqu'ici c'est okay.
    - 1 mutex, pour des échanges entre 2 threads pourquoi pas, mais pour 11?
    - 2 cond_var, est-ce assez?
    - 3 variables échangées (*null et *null1 et *ko) dont 2 sont quasi-protégés. Et la troisième porte bien son nom, elle est utilisée en écriture par 11 threads et n'est jamais protégée, c'est un beau chaos.
    - un certain nombre de pointeurs
    - et même des malloc... Tu n'as pas dû comprendre quand il faut des malloc.

    Seuls 2 pointeur sont utile, tu les as nommés très 'explicitement' a et b. Les autres, bof! Les pointeurs devaient être en promo, mais à cause d'eux le code est plus complexe à lire. Il faut simplifier.

    Alors combien te faut-il de cond_var, de mutex, de variables échangées, ...?
    Mais surtout : Quel est l'objectif? Quelle séquence de déroulement cherches tu à établir? Comment décomposer tout ça? Peut-être qu'un dessin serait utile?

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

Discussions similaires

  1. Problème de communications entre threads
    Par maya09 dans le forum Windows
    Réponses: 1
    Dernier message: 22/02/2006, 23h18
  2. Communication entre thread
    Par JFPS Soft dans le forum Concurrence et multi-thread
    Réponses: 2
    Dernier message: 03/02/2006, 18h38
  3. [c#][threading] communication entre threads
    Par orelero dans le forum C#
    Réponses: 6
    Dernier message: 02/01/2006, 01h42

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