進程及線程管理實驗2

實驗來自《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

                                                                                                  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章