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:
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?
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?
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;
}
扔个三星炸死你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_signal
is 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.