Maison  >  Questions et réponses  >  le corps du texte

linux - Comment comprendre les verrous mutex et les variables de condition?

Le code suivant est tiré du "Tutoriel pratique de programmation Unix/Linux". Sa fonction est d'utiliser deux threads pour compter le nombre de mots dans deux fichiers respectivement et de calculer le nombre total dans le thread principal. Ci-dessous une capture d'écran de l'opération :

Mais après l'avoir lu longuement, il est encore difficile de comprendre les variables de verrouillage, de déverrouillage et de condition dans le code suivant.
Je veux demander :

  1. Lors de l'appel de pthread_cond_wait时会释放互斥锁,然后挂起主线程,并等待条件变量的发生变化,当其他线程调用pthread_cond_signal时,如果互斥锁是被锁住的,那么主线程中的pthread_cond_wait dans le fil de discussion principal, attendra-t-il que le mutex soit déverrouillé, puis verrouillera-t-il le mutex avant de revenir ?

  2. Si c'est comme décrit en 1, pthread_cond_wait收到了pthread_cond_signal发来的信号,但是未锁定互斥锁之前,又被其他线程抢了先,锁住了互斥锁,那不是pthread_cond_waitdoit-il encore attendre que le verrou mutex soit déverrouillé ?

  3. Si possible, j'espère que cela pourra aider à clarifier le processus d'exécution de ce programme.

Merci beaucoup.

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <ctype.h>

struct arg_set {            /* two values int one arg */
    char    *filename;      /* file to examine */
    int     count;          /* number of words */
    int     code;
};

struct arg_set  *mailbox = NULL;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  flag = PTHREAD_COND_INITIALIZER;

void *count_words(void *);

int main(int argc, char *argv[])
{
    pthread_t t1, t2;               /* two threads */
    struct arg_set args1, args2;    /* two argsets */
    int reports_int = 0;
    int total_words = 0;

    if (argc != 3) {
        fprintf(stderr, "usage: %s file1 file2", argv[0]);
        exit(1);
    }

    pthread_mutex_lock(&lock);

    args1.filename  = argv[1];
    args1.count     = 0;
    args1.code      = 1;
    pthread_create(&t1, NULL, count_words, (void *)&args1);

    args2.filename  = argv[2];
    args2.count     = 0;
    args2.code      = 2;
    pthread_create(&t2, NULL, count_words, (void *)&args2);

    while (reports_int < 2) { // 等待其他线程结束
        printf("MAIN: waiting for flag to go up\n");
        pthread_cond_wait(&flag, &lock);
        printf("MAIN: Wow! flag was raised, I have the lock\n");
        printf("%7d: %s\n", mailbox->count, mailbox->filename);
        total_words += mailbox->count;
        if (mailbox == &args1)
            pthread_join(t1, NULL);
        if (mailbox == &args2)
            pthread_join(t2, NULL);
        mailbox = NULL;
        pthread_cond_signal(&flag);
        reports_int++;
    }

    printf("%7d: total words\n", total_words);

    return 0;
}

void *count_words(void *a)
{
    struct arg_set *args = a;
    FILE *fp;
    int c, prevc = 'rrreee';

    if ((fp = fopen(args->filename, "r")) != NULL) { // 统计单词个数
        while ((c = getc(fp)) != EOF) {
            if (!isalnum(c) && isalnum(prevc))
                args->count++;
            prevc = c;
        }
        fclose(fp);
    } else
        perror(args->filename);

    printf("COUNT %d: waiting to get lock\n", args->code);
    pthread_mutex_lock(&lock);
    printf("COUNT %d: have lock, storing data\n", args->code);
    if (mailbox != NULL)
        pthread_cond_wait(&flag, &lock);
    mailbox = args;
    printf("COUNT %d: raising flag\n", args->code);
    pthread_cond_signal(&flag);
    printf("COUNT %d: unlocking box\n", args->code);
    pthread_mutex_unlock(&lock);

    return NULL;
}
仅有的幸福仅有的幸福2685 Il y a quelques jours1168

répondre à tous(1)je répondrai

  • 扔个三星炸死你

    扔个三星炸死你2017-06-12 09:26:46

    Rien de compliqué. Une fois que le thread principal a obtenu le verrou, il se met en veille et attend un signal pour le réveiller.

    pthread_cond_signalC'est le signal

    Ce type de verrou est un peu différent des autres verrous. Les autres types de verrous sont : le fil demande un verrou, et s'il n'obtient pas le verrou, le fil se met en veille et attend.

    Ce type de verrou se met en veille lorsqu'il est verrouillé, en attendant que d'autres threads le réveillent.

    répondre
    0
  • Annulerrépondre