实验来自《UNIX操作系统实验教程》

实验内容:

编写一段程序创建两个子线程,分别对两个文件的字数进行统计,两个线程统计完后写入到子线程与父线程共享的一块内存(变量)中,然后父线程从这一块内存中读取相应的信息。注意线程的同步和互斥。

源代码:

#include

#include

#include

#include

 

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 <

> @1 2$%^$%3

>  4hd

> eof

[huazi@huazi ~]$ cat >pthread_3.tmp2 <

> 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