實驗來自《UNIX操作系統實驗教程》
實驗內容:
編寫一段程序創建兩個子線程,分別對兩個文件的字數進行統計,兩個線程統計完後寫入到子線程與父線程共享的一塊內存(變量)中,然後父線程從這一塊內存中讀取相應的信息。注意線程的同步和互斥。
源代碼:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <ctype.h>
struct arg_set {
char *fname;//檢驗的文件
int count;//單詞計數
};
struct arg_set * mailbox = NULL;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t flag = PTHREAD_COND_INITIALIZER;
int main(int ac,char *av[])
{
pthread_t t1,t2;//兩個線程
struct arg_set args1,args2;
void *count_words(void *);
int reports_in=0;
int total_words=0;
if(ac != 3){
printf("usage:%s file1 file2\n",av[0]);
exit(1);
}
pthread_mutex_lock(&lock);//主線程先鎖定臨界資源
args1.fname=av[1];
args1.count=0;
pthread_create(&t1,NULL,count_words,(void *)&args1);
args2.fname=av[2];
args2.count=0;
pthread_create(&t2,NULL,count_words,(void *)&args2);
while(reports_in<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->fname);//這裏的fname指針是這樣用的,c語言裏,字符串當做數組看,自然取首地址
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_in++;
}
printf("%7d:total words\n",total_words);
return 0;
}
void *count_words(void *a)
{
struct arg_set *args=a;//void型可以賦給任何類型,反之不行。這是爲了使得arg返回到正確類型上
FILE * fp;
int c,prevc='\0';
if((fp=fopen(args->fname,"r"))!=NULL){
while((c=getc(fp))!=EOF){
if(!isalnum(c) && isalnum(prevc))
args->count++;
prevc=c;
}
fclose(fp);
} else
perror(args->fname);
printf("count(%lu):waiting to get lock\n",pthread_self());
pthread_mutex_lock(&lock);//當前線程獲得mailbox這個臨界資源
printf("count(%lu):have lock,storing data\n",pthread_self());
if(mailbox!=NULL){
printf("count(%lu):oops..mailbox not empty.wait for signal\n",pthread_self());
pthread_cond_wait(&flag,&lock);//主線程正在對臨界資源進行操作,等待主線程喚醒
}
mailbox=args;//地址複製給mailbox
printf("count(%lu):raising flag\n",pthread_self());
pthread_cond_signal(&flag);//這時候,可以喚醒主線程的等待,對mailbox即將鎖定
printf("count(%lu):unlocking box\n",pthread_self());
pthread_mutex_unlock(&lock);//子線程解鎖mailbox,即釋放mailbox,這時候,主線程的cond_wait函數可以對它鎖定
return NULL;
}
建兩個文件
[huazi@huazi ~]$ cat >pthread_3.tmp1 <<eof
> @1 2$%^$%3
> 4hd
> eof
[huazi@huazi ~]$ cat >pthread_3.tmp2 <<eof
> abcde
> of
> gh
> ij
> 5
> eof
[huazi@huazi ~]$ gcc -lpthread pthread_3.c -o pthread_3.o
[huazi@huazi ~]$ ./pthread_3.o pthread_3.tmp1 pthread_3.tmp2
main:waiting for flag to go up
count(3078351728):waiting to get lock
count(3078351728):have lock,storing data
count(3078351728):raising flag
count(3078351728):unlocking box
main:wow!flag was raised,I have the lock
4: pthread_3.tmp1
main:waiting for flag to go up
count(3067861872):waiting to get lock
count(3067861872):have lock,storing data
count(3067861872):raising flag
count(3067861872):unlocking box
main:wow!flag was raised,I have the lock
5: pthread_3.tmp2
9:total words