search

Home  >  Q&A  >  body text

linux - How to understand mutex locks and condition variables?

The following code comes from "Unix/Linux Programming Practice Tutorial". Its function is to use two threads to count the number of words in two files respectively, and calculate the total number in the main thread. The following is a running screenshot:

But after reading it for a long time, it is still difficult to understand the locking, unlocking and condition variables in the following code.
I want to ask:

  1. When pthread_cond_wait is called in the main thread, the mutex lock will be released, and then the main thread will be suspended and wait for the condition variable to change. When other threads call pthread_cond_signal , if the mutex is locked, will pthread_cond_wait in the main thread wait for the mutex to be unlocked, then lock the mutex before returning?

  2. If it is as described in 1, pthread_cond_wait received the signal from pthread_cond_signal, but before the mutex was locked, it was snatched by other threads First, if the mutex is locked, doesn't it mean that pthread_cond_wait still has to wait for the mutex to be unlocked?

  3. If possible, I hope it can help clarify the execution process of this program.

Many thanks.

#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;
}
仅有的幸福仅有的幸福2767 days ago1251

reply all(1)I'll reply

  • 扔个三星炸死你

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

    Nothing complicated. After the main thread obtains the lock, it goes to sleep and waits for a signal to wake it up.

    pthread_cond_signalis this signal

    This kind of lock is a little different from other locks. Other types of locks are: the thread applies for a lock, and if it does not get the lock, the thread goes to sleep and waits.

    This kind of lock sleeps when it is locked, waiting for other threads to wake it up.

    reply
    0
  • Cancelreply