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

C Discussion :

Multithreading - Sémaphore - Dîner des Philosophes


Sujet :

C

  1. #1
    Membre à l'essai
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mars 2014
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2014
    Messages : 21
    Points : 18
    Points
    18
    Par défaut Multithreading - Sémaphore - Dîner des Philosophes
    Bonjour à tous,

    Voilà depuis quelques semaines j'étudie (en cours) la programmation système en C sous Linux. Ayant bien galéré à l'école, j'ai décidé de m'y replonger totalement pour bien comprendre et assimiler. Actuellement je bloque sur le TP "final" de la partie Threads et Sémaphore (Pour ceux qui connaisse il s'agit du Problème du dîner des philosophes).
    Voici l'énoncé :
    On rappelle qu’un nombre n (pour ma part n = 5) de philosophes sont assis autour d’une table ronde, sur laquelle sont installées n assiettes de spaghettis et n fourchettes. Chaque philosophe dispose d’une fourchette de chaque côté de son assiette.
    Les philosophes commencent tous à penser. Lorsque l’un d’eux se décide à faire une pause pour manger, il cherche à prendre les deux fourchettes qui se trouvent de chaque côté de son assiette. Si un de ses voisins mange, il devra attendre… Si une des deux fourchettes est occupée par un voisin, il devra attendre. Le programme prend fin dès que NBCYCLES cycles penser-manger ont été réalisés par chaque philosophe. L'affichage devra se faire sur une seule ligne représentant l'état de chaque Philosophe (P P P P P). On doit afficher seulement quand il y a Changement d'Etat d'1 Philosophe (P P P P P , P P P P A, P P P P M, P P P A M, etc...).
    Le schéma du système :

    Bien sûr ce système est connu pour être bloquant. J'ai donc choisi d'utiliser un tableau de sémaphores "privé", 1 pour chaque philosophe en attente de ses fourchettes. Les états des philosophes sont stockés dans un tableau. J'utilise donc un sémaphore "public" de type mutex pour la section critique Tableau d'état.
    Déjà voilà mon code :
    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
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    /**************************************
    ** pthread-philo2.c
    **
    ** Programme d'exemple de pthread avec
    ** philosophes qui dinent et mutex
    **
    ***************************************/
     
    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    #include <unistd.h>
    #include <semaphore.h>
    #include <errno.h>
    #include <string.h>
     
    #define NB_PHILO 5
    #define NB_CYCLE 5
     
    typedef enum{Pense, Mange, Attend} T_etat;
     
    T_etat etatPhilo[NB_PHILO];
     
    static sem_t fourchettes[NB_PHILO]; // sémaphore privé, sémaphore pour les ressources fourchettes (1 par philosophe)
    static sem_t SemaPublic; // pour l'affichage (il faut pas que ça change pendant qu'on affiche)
     
     
     
    void error(int err, char *msg) {
        fprintf(stderr,"%s a retourné %d message d'erreur : %s\n",msg,err,strerror(errno));
        exit(EXIT_FAILURE);
    }
     
    void changeEtaffiche ( int* id, T_etat nouvelEtat)  // fonction affichant les états des différents philosophes sur une ligne
    {
        int i;
        sem_wait(&SemaPublic);
        etatPhilo[*id] = nouvelEtat;
        for (i = 0; i<NB_PHILO; i++)
        {
            switch(etatPhilo[i]){
                case Pense: printf(" P "); break;
                case Mange: printf(" M "); break;
                case Attend: printf(" A "); break;
            }
        }
        printf("\n\n");
        sem_post(&SemaPublic);
    }
     
     
     
    void* philosophe ( void* arg )
    {
        int *id=(int *) arg;
        int left = *id;
        int right = (left + 1) % NB_PHILO;
     
        int cycle;
        for(cycle=0; cycle<NB_CYCLE; cycle++) {
     
            // il attend
            changeEtaffiche(id,Attend);
            if(left<right) {
                sem_wait(&fourchettes[left]);
                sem_wait(&fourchettes[right]);
            }
            else {
                sem_wait(&fourchettes[right]);
                sem_wait(&fourchettes[left]);
            }
     
            // il mange
            changeEtaffiche(id,Mange);
            //sleep(2);
     
            // il pense (important: avant de relacher ses fourchette, parce que s'il le fait après, l'affichage mettrait que 2 voisins mange en même temps)
            changeEtaffiche(id,Pense);
            sem_post(&fourchettes[left]);
            sem_post(&fourchettes[right]);
     
            //sleep(2);
     
        }
        return (NULL);
    }
     
    /*********************
    ***** MAIN
    *********************/
    int main ( int argc, char *argv[])
    {
        int i;
        int id[NB_PHILO];
        int err;
        pthread_t thread[NB_PHILO]; // threads philosophes
     
        srand(getpid());
     
        sem_init(&SemaPublic,0,1);
     
        for (i = 0; i < NB_PHILO; i++) {
            id[i]=i;
            etatPhilo[i] = Pense;       // au début TOUS les philosophes pensent
            err=sem_init( &fourchettes[i], 0, 1);
            if(err!=0)
                error(err,"sem_init");
        }
     
        for (i = 0; i < NB_PHILO; i++) {
            err=pthread_create(&thread[i], NULL, philosophe, (void*)&(id[i]) );
            if(err!=0)
                error(err,"pthread_create");
        }
     
        for (i = 0; i < NB_PHILO; i++) {
            pthread_join(thread[i], NULL);
            if(err!=0)
                error(err,"pthread_join");
        }
     
        for (i = 0; i < NB_PHILO; i++) {
            sem_destroy(&fourchettes[i]);
            if(err!=0)
                error(err,"pthread_mutex_destroy");
        }
     
        sem_destroy(&SemaPublic);
     
        return (EXIT_SUCCESS);
    }
    Ce code compile et s'exécute.
    J'ai plusieurs problèmes :
    1. Déjà je n'arrive pas à afficher QUE quand il y a changement d'état d'un philosophe (vous verrez qu'on a un affichage de 5 lignes en même temps et plusieurs fois la même ligne s'affiche à la suite)
    2. J'ai l'impression que plusieurs philosophes ne peuvent pas manger en même temps (alors que par exemple philo 0 et philo 2 pourraient..) et à chaque fois j'ai une ligne où les 5 philosophes attendent et ce toutes les 3 lignes affichées.
    3. Je n'arrive pas à gérer le fait que quand chaque philosophe aura manger X fois il reste en état pense et que quand tous les philos ont mangés X fois et sont en état Pense, le programme se termine.

    Pour mes 1ère et 2è questions c'est au niveau des sémaphores que cela se passe je le sais. Et c'est sur cette partie que je bloque le plus, donc hésitez pas à critiquer mon code et surtout à bien m'expliquer pourquoi ça plutôt que comme moi j'ai fait.
    Je veux vraiment afficher une ligne quand UN etat d'UN philosophe change et je ne veux pas que ca fasse les philosophes les uns après les autres (n°0 mange, puis pense, n°1 mange puis pense etc..) comme cela fait quand on exécute mon code.

    Désolé de la taille du poste (j'aime bien détailler et expliquer ce que je veux vraiment). Si vous avez mal compris des choses, demandez ^^
    Merci d'avance à ceux qui prendront le temps de me lire et de me répondre
    Je compte sur votre aide^^
    Cordialement,
    Fuot

  2. #2
    Membre émérite
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    852
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 852
    Points : 2 298
    Points
    2 298
    Par défaut
    Désolé de la taille du poste (j'aime bien détailler et expliquer ce que je veux vraiment). Si vous avez mal compris des choses, demandez ^^
    Au contraire, c'est une excellente chose et ca facilite notre demarche pour t'aider sans parler du fait que c'est plus agreable.

    1. Déjà je n'arrive pas à afficher QUE quand il y a changement d'état d'un philosophe (vous verrez qu'on a un affichage de 5 lignes en même temps et plusieurs fois la même ligne s'affiche à la suite)
    Je pense que c'est a cause du buffering de printf. En gros, si tu veux etre sur qu'il affiche le texte que tu lui as envoye, il faut qu'il y ait un retour a la ligne a la fin de la chaine de caracteres. Exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    printf("test"); //peut ne pas s'afficher immediatement
    printf("test\n"); //sera affiche immediatement
    2. J'ai l'impression que plusieurs philosophes ne peuvent pas manger en même temps (alors que par exemple philo 0 et philo 2 pourraient..) et à chaque fois j'ai une ligne où les 5 philosophes attendent et ce toutes les 3 lignes affichées.
    Je pense qu'avant meme de regarder tes fonctions, ton probleme n'est pas super bien pose. Lorsque je suis tombe sur ce projet (il y a 1 ou 2 ans maintenant) a mon ecole, je m'y etais pris de cette facon :

    - l'element bloquant est clairement les fourchettes donc autant creer un mutex par fourchette.
    - pour gerer plus facilement ces fourchettes et ces philosophes, autant creer des structures qui vont les gerer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    struct philosophe
    {
      struct fourchette *main_droite;
      struct fourchette *main_gauche;
      int                     etat;
    };
     
    struct fourchette
    {
      struct philosophe *mangeur;
      semaphore          mutex;
    };
    Avec ca tu devrais deja y voir un peu plus clair.

    3. Je n'arrive pas à gérer le fait que quand chaque philosophe aura manger X fois il reste en état pense et que quand tous les philos ont mangés X fois et sont en état Pense, le programme se termine.
    Il te suffit de rajouter une variable dans la structure philosphe qui permette de savoir combien de fois il a mange. Il te suffira de verifier a chaque tour si tous les philosophes ont mange X fois ou non.

    En esperant t'avoir aide.

  3. #3
    Membre à l'essai
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mars 2014
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2014
    Messages : 21
    Points : 18
    Points
    18
    Par défaut
    Salut à toi et merci de te réponse

    Pour l'affichage à chaque Changement d'Etat, j'ai réussi, cela affiche une ligne quand un philosophe change d'état. Merci à toi.
    Par contre cela s'affiche par 5 lignes en même temps à chaque fois, moi je veux une ligne à la fois, 1 seconde entre chaque, tout en gérant ce que j'ai dit juste au dessus.

    Pour le reste j'ai corrigé plusieurs choses c'est pratiquement parfait^^ : 2 philosophes arrivent à manger en même temps (j'ai utilisé des sémaphores pour chaque fourchette), et j'ai introduit une variable cycle : quand chaque philosophe a fait 3 cycles (Penser-Manger), le programme se termine.

    PAR CONTRE j'ai toujours, toutes les 5-6 lignes, tous les philosophes repassent à ATTEND, et à chaque fois... et j'arrive vraiment pas à voir le problème en fait.

    J'ai mis à jour le code dans le 1er Post, vous pouvez m'aider, à partir de mon code svp ???

    Merci encore des aides et infos en tout cas, ca m'a aidé

Discussions similaires

  1. [C#] multithread et gestion des exceptions
    Par JuTs dans le forum Développement Windows
    Réponses: 11
    Dernier message: 20/07/2010, 23h28
  2. [WD12-14] Multithread, Sémaphores ?
    Par peijnoob dans le forum WinDev
    Réponses: 5
    Dernier message: 10/02/2009, 20h18
  3. probleme des philosophes en java
    Par esthr dans le forum Général Java
    Réponses: 5
    Dernier message: 07/06/2008, 22h24
  4. probleme des philosophes en C
    Par esthr dans le forum C
    Réponses: 6
    Dernier message: 04/10/2007, 17h51
  5. probleme des philosophes en c++
    Par esthr dans le forum C++
    Réponses: 2
    Dernier message: 04/10/2007, 16h13

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