Partage
  • Partager sur Facebook
  • Partager sur Twitter

thread : pourquoi avec un sleep ca marche ?

thread : pourquoi avec un sleep ca marche ?

    29 décembre 2019 à 20:40:56

    /*
    Je me suis décidé à continuer l'apprentissage du C avec les threads.
    Voici donc mon travail
    
    EXPLICATION : 
    On a créé deux threads
    
    worker va boucler et à chaque itération, va print le tour et le numéro d'itération
    avant d'activer une condition nommée cond
    le thread de la fonction message va se mettre en route quand la condition sera activée
    il va vérifier que la valeur de isFinished n'a pas été changé (le thread message ne s'arretera que quand isFinished vaudra 1
    il va ensuite print ok et incrémenter count (une variable pour débugger que je printerai à la fin pour voir combien de fois
    message a été exécuté.
    quand worker a fini de boucler, il met isFinished à 1 (parce que c'est fini) et il appelle message pour que ce dernier constate le changement de isFinished et qu'il s'arrete.
    
    Mon pb : de base le programme marchait pas et j'ai rajouté des sleep entre chaque changement de condition pour voir si ca changait quelque chose : ca s'est mis à fonctionner
    quand j'ai enlevé le sleep tout au début, à la première itération, l'appel à message n'a pas fonctionné. Quand on enlève le sleep à la fin de la boucle for, 
    c'est tous les autres changements de la condition qui ne marchent plus. Chaque fois, pour fonctionner, il faut qu'il y ait une pause de 1. J'ai changé la valeur
    pour mettre 0.5 et ca n'a pas fonctionné. Je suis perdu. Est ce que c'est une faute de ma part ? Pourquoi ca fait ca ?
    
    */
    
    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>
    
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //le mutex
    pthread_cond_t cond = PTHREAD_COND_INITIALIZER; //la condition
    
    int isFinished=0; //isFinishge
    int count=0; //une valeur de debug qui représente le nombre de fois ou message a été "appellé"
    void *worker(void* args){
        sleep(1);
        unsigned int i=0;
        for(; i<10; i++){
            pthread_mutex_lock(&mutex);
            printf("tour %d : ", i); //on affiche le nombre d'itérations
            pthread_cond_signal(&cond); //on lance messgae
            pthread_mutex_unlock(&mutex);
            sleep(1);
        }
        isFinished=1; //on met isFinished à 1...
        pthread_mutex_lock(&mutex);
        pthread_cond_signal(&cond); //... on met en route message pour qu'il vérifie
        pthread_mutex_unlock(&mutex);
        pthread_exit(NULL);
    }
    
    void* message(void* args){
        int onContinue=0;
        while(!onContinue){
            pthread_mutex_lock(&mutex);
            pthread_cond_wait(&cond, &mutex); // on attend l'activation de la condition
            puts("ok"); //on affiche un message
            onContinue=isFinished; // je mets la valeur de isFinished dans onContinue (si isFinished a changé, la boucle s'arretera)
            count++; //ma petite valeur de debug
            pthread_mutex_unlock(&mutex);
        }
        pthread_exit(NULL);
    }
    
    int main(){
        pthread_t pid; //on fait nos threads
        pthread_t pid2;
        pthread_create(&pid, NULL, worker, (void*)NULL);
        pthread_create(&pid2, NULL, message, (void*)NULL);
        pthread_join(pid, NULL);
        pthread_join(pid2, NULL);
        printf("%d\n", count); //j'affiche le nombre de fois ou message a été appellé
        return 0;
    }
    

    -
    Edité par *** --Kamazoultane-- *** 29 décembre 2019 à 20:41:37

    • Partager sur Facebook
    • Partager sur Twitter
    "Science sans conscience n'est que ruine de l'âme."  citation de Rabelais (1494-1553)
      1 janvier 2020 à 8:11:21

      Salut,
      Je ne trouve pas 'pthread_join' sur mon système. Est-ce dans une librairie spéciale?
      Si je veux tester ton code, ça me la prend.
      Tu dis appeler sleep avec 0.5 secondes, le paramètre est un 'unsigned int'.
      Tu aurais dû avoir une erreur du compilateur, ou bien il l'a converti en 0.
      • Partager sur Facebook
      • Partager sur Twitter

      Le Tout est souvent plus grand que la somme de ses parties.

        15 janvier 2020 à 16:13:15

        Bonjour, désolé de répondre aussi tard.. 

        pthread_join est dans la librairie pthread.h (page du manuel linux : http://manpagesfr.free.fr/man/man3/pthread_join.3.html )

        j'ai du oublier de préciser en revanche que le programme doit etre compilé avec l'option -lpthread (le cours "https://openclassrooms.com/fr/courses/1513891-la-programmation-systeme-en-c-sous-unix/1514567-les-threads" donne la commande " gcc -lpthread main.c -o monProgramme " ca m'a d'ailleurs un peu surpris d'avoir à donner une option en plus à gcc pour mettre des threads)

        D'ailleurs, mon code est inspiré du dernier programme qu'ils ont donné

        Pour ce qui est de la commande sleep, je pense que le compilateur l'a effectivement converti en 0 (ce qui explique pourquoi ca n'a pas fonctionné :p ). J'étais au lycée et comme ils n'ont pas gcc et que nous n'avons les droits d'admin (encore heureux :p), j'ai utilisé https://www.onlinegdb.com/online_c_compiler (il y a gdb dessus, c'est super cool). 

        Merci beaucoup pour ta réponse en tout cas. 

        -
        Edité par *** --Kamazoultane-- *** 15 janvier 2020 à 16:21:55

        • Partager sur Facebook
        • Partager sur Twitter
        "Science sans conscience n'est que ruine de l'âme."  citation de Rabelais (1494-1553)
          15 janvier 2020 à 17:13:48

          Salut,
          Merci pour ces précisions.
          Par contre, je suis sur Windows 10 et je ne sais pas si cela va fonctionner. Je vais voir ce que je peux faire.
          -
          J'ai compilé avec -lpthread et Ça compile et ça exécute.
          J'ai vérifié avec et sans les sleep() et je vois la différence.
          J'ai remplacé les sleep() par des boucles du genre:
          for (int slms = 0; slms < 1000000000; slms++);
          Cela semble boucler environ une seconde sur mon ordi.
          J'ai divisé par 10 3 fois pour avoir ce que je pense être 1 milliseconde.
          Et ça fonctionne toujours.
          C'est plus ou moins le temps que prend un processus pour démarrer ou être cédulé.
          Je suppose que le céduleur de Windows est appelé toutes les millisecondes pour ré-évaluer ses tâches.
          Ça ne marche plus avec 100000 (0.1 ms).

          -
          Edité par PierrotLeFou 17 janvier 2020 à 5:14:31

          • Partager sur Facebook
          • Partager sur Twitter

          Le Tout est souvent plus grand que la somme de ses parties.

            17 janvier 2020 à 19:38:21

            eh bien merci beaucoup de ton aide. Je dois t'avouer être quelque peu satisfait parce que étant donné que c'était une toute nouvelle notion, je m'attendais plus à une grosse erreur de programmation (et là du coup, il semblerait qu'il n'y en ait pas). Merci beaucoup en tout cas :D

            • Partager sur Facebook
            • Partager sur Twitter
            "Science sans conscience n'est que ruine de l'âme."  citation de Rabelais (1494-1553)
              18 janvier 2020 à 0:00:00

              Bonjour,

              Tu indiques qu'avec un sleep() ça marche et que sans ça ne marche pas. Mais tu n'indiques pas ce que tu entends par "ça marche".

              Ce que je lis :
              - un premier thread va compter de 0 à 9 et signaler 11 fois.
              - un second thread va afficher "ok" à chaque fois qu'il est débloqué par un signal. Donc ce thread va afficher "ok" au moins une fois et au maximum 11 fois. Et le compteur indique le nombre de "ok" qu'il y a eu.
              En ralentissant le premier thread avec des sleep(), on augmente la probabilité d'avoir les 11 "ok".

              • Partager sur Facebook
              • Partager sur Twitter

              En recherche d'emploi.

                26 janvier 2020 à 13:14:18

                oui excuse moi. Pour que ca marche, il faut que le premier thread affiche le numéro du tour à chaque itération (10 premières fois) et que juste après le deuxième thread envoie ok. Ensuite, on va changer la valeur de isFinsihed. Là, il faut que le deuxième thread envoie à nouveau ok avant de s'arreter.

                Du coup en output, on aurait:

                tour 0 : ok

                tour 1 : ok

                […]

                tour 9 : ok

                ok

                11

                -
                Edité par *** --Kamazoultane-- *** 26 janvier 2020 à 13:16:50

                • Partager sur Facebook
                • Partager sur Twitter
                "Science sans conscience n'est que ruine de l'âme."  citation de Rabelais (1494-1553)

                thread : pourquoi avec un sleep ca marche ?

                × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                • Editeur
                • Markdown