下面的代码出自《Unix/Linux编程实践教程》,作用是用两个线程分别统计两个文件的单词的数目,并在主线程中计算总数。下面是运行截图:
但是看了半天还是难以理解下面代码中的加锁、解锁以及条件变量。
我想问:
主线程中调用pthread_cond_wait
时会释放互斥锁,然后挂起主线程,并等待条件变量的发生变化,当其他线程调用pthread_cond_signal
时,如果互斥锁是被锁住的,那么主线程中的pthread_cond_wait
会等互斥待锁被解锁后,然后再给互斥锁上锁后再返回吗?
如果正如1中的描述那样的话,pthread_cond_wait
收到了pthread_cond_signal
发来的信号,但是未锁定互斥锁之前,又被其他线程抢了先,锁住了互斥锁,那不是pthread_cond_wait
还得挂起等待互斥锁被解锁?
如果可以的话,希望能帮助理清一下这个程序的执行流程。
万分感谢。
#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;
}
没什么复杂的,主线程获得锁后,进入休眠,等一个信号来唤醒它。
pthread_cond_signal
就是这个信号这种锁与别的锁有点不同,其它类型的锁是:线程申请锁,没有得到锁,线程就进入休眠,等待。
这种锁是有锁就休眠,等别的线程叫醒它。