Linux 线程示例

11 篇文章 0 订阅
Linux 线程示例,原程序摘自Bruce Molay 的<<Understanding Unix/Linux Programing >>中第十四章的twordcount.c程序,将原来只能用两个线程为两个文件计数扩展为用三个线程为三个文件计数.
程序使用一个条件变量flag,一个互斥锁lock和一个全局变量mailbox来协同三个计数线程同时对三个文件的词数进行计数.主线程需要flag来指示mailbox中有消息,计数线程需要lock来协调对mailbox的写权限,并检查mailbox为空时才可覆盖.
在原来的程序中计数线程使用 pthread_cond_wait来检测mailbox是否为空,若只是单纯的增加线程进行扩展,会造成死锁,主线程和计数线程都在等待flag条件变量,必须将其修改为释放lock和再要求lock才不会造成死锁:
修改段如下:
原来:
if  ( mailbox  !=  NULL ) {
        printf(
"COUNT: oops..mailbox not empty. wait for signal ");
        pthread_cond_wait(
&flag,&lock);
}

修改为:
while (mailbox  !=  NULL)  {        // if the mailbox is not empty,wait
        pthread_mutex_unlock(&lock);
        pthread_mutex_lock(
&lock);
        
// pthread_cond_wait(&flag,&lock);
}
不可只是将if改为while应付了事.原来的用两个线程处理两个文件的程序最好也改用此段代码.

切记:
pthread_cond_wait(&flag,&lock); 释放lock,并等待flag,等到获得flag后会自动等待lock,之后再返回调用函数处.

完整程序:
/*******************************************************************
 * twordcount.c - thread word counter for two files
 * condition variable allows counter fuctions 
 *     to report result early
 
*/

#include 
< stdio.h >
#include 
< stdlib.h >
#include 
< pthread.h >
#include 
< ctype.h >

struct  arg_set  {                // two values in one arg
    char *fname;                // file to examine
    int count;                // number of words
    int thread_id;                // thread id
}
;

struct  arg_set  * mailbox;
pthread_mutex_t 
lock   =  PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t flag 
=  PTHREAD_COND_INITIALIZER;

int  main( int  argc, char   * argv[])  {
    pthread_t t1,t2,t3;
    
struct arg_set args1,args2,args3;    // two threads
    void *count_words(void *);        // two argsets
    int reports_in = 0;
    
int total_words = 0;

    
if(argc != 4{
        fprintf(stderr,
"Usage: %s file1 file2 file3 ",argv[0]);
        exit(
1);
    }


    pthread_mutex_lock(
&lock);        // lock the report box now
    
    args1.fname 
= argv[1];
    args1.count 
= 0;
    args1.thread_id 
= 1;
    pthread_create(
&t1,NULL,count_words,(void *)&args1);

    args2.fname 
= argv[2];
    args2.count 
= 0;
    args2.thread_id 
= 2;
    pthread_create(
&t2,NULL,count_words,(void *)&args2);

    args3.fname 
= argv[3];
    args3.count 
= 0;
    args3.thread_id 
= 3;
    pthread_create(
&t3,NULL,count_words,(void *)&args3);

    
while(reports_in < 3{
        printf(
"MAIN: waiting for flag to go up ");
        pthread_cond_wait(
&flag,&lock);    // wait for notify
        printf("MAIN: Wow!flag was raised, I have the lock ");
        printf(
"%7d: %s ",mailbox->count,mailbox->fname);
        total_words 
+= mailbox->count;
        
        
if(mailbox == &args1)
            pthread_join(t1,NULL);
        
if(mailbox == &args2)
            pthread_join(t2,NULL);
        
if(mailbox == &args3)
            pthread_join(t3,NULL);
        mailbox 
= NULL;
        pthread_cond_signal(
&flag);
        
++reports_in;
    }

    printf(
"%7d: total word ",total_words);

    
return 0;
}


void   * count_words( void   * a)  {
    
struct arg_set *args = a;        // casts arg back to correct type
    FILE *fp;
    
int c,id = args->thread_id,prevc = '';

    
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%d: waiting to get lock ",id);
    pthread_mutex_lock(
&lock);        // get the mailbox
    printf("COUNT%d: have lock,storing data ",id);
    
while(mailbox != NULL) {        // if the mailbox is not empty,wait
        pthread_mutex_unlock(&lock);
        pthread_mutex_lock(
&lock);
        
// pthread_cond_wait(&flag,&lock);
    }

    mailbox 
= args;                // put ptr to our args there
    printf("COUNT%d: rasing flag ",id);
    pthread_cond_signal(
&flag);        // raise the flag
    printf("COUNT%d: unlocking box ",id);
    pthread_mutex_unlock(
&lock);        // release the mail box

    
return NULL;
}

 原书的两计数线程处理两文件程序:
/* twordcount4.c - threaded word counter for two files.    
 *         - Version 4: condition variable allows counter
 *                            functions to report results early 
 
*/


#include  
< stdio.h >
#include  
< pthread.h >
#include  
< ctype.h >

struct  arg_set  {        /* two values in one arg*/
        
char *fname;    /* file to examine    */
        
int  count;    /* number of words    */
}
;

struct  arg_set   * mailbox  =  NULL;
pthread_mutex_t 
lock   =  PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  flag 
=  PTHREAD_COND_INITIALIZER;

main(
int  ac,  char   * av[])
{
    pthread_t      t1, t2;        
/* two threads */
    
struct arg_set args1, args2;    /* two argsets */
    
void           *count_words(void *);
    
int            reports_in = 0;
    
int           total_words = 0;

    
if ( ac != 3 ){
        printf(
"usage: %s file1 file2 ", av[0]);
        exit(
1);
    }

    pthread_mutex_lock(
&lock);    /* lock the report box now */

    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 ");
        pthread_cond_wait(
&flag, &lock); /* wait for notify */
        printf(
"MAIN: Wow! flag was raised, I have the lock ");
        printf(
"%7d: %s ", mailbox->count, mailbox->fname);
        total_words 
+= mailbox->count;
        
if ( mailbox == &args1) 
            pthread_join(t1,NULL);
        
if ( mailbox == &args2) 
            pthread_join(t2,NULL);
        mailbox 
= NULL;
        pthread_cond_signal(
&flag);    /* announce state change */
        reports_in
++;
    }

    printf(
"%7d: total words ", total_words);
}

void   * count_words( void   * a)
{
    
struct arg_set *args = a;    /* cast arg back to correct type */
    FILE 
*fp;
    
int  c, prevc = '';
    
    
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: waiting to get lock ");
    pthread_mutex_lock(
&lock);    /* get the mailbox */
    printf(
"COUNT: have lock, storing data ");
    
if ( mailbox != NULL ){
        printf(
"COUNT: oops..mailbox not empty. wait for signal ");
        pthread_cond_wait(
&flag,&lock);
    }

    mailbox 
= args;            /* put ptr to our args there */
    printf(
"COUNT: raising flag ");
    pthread_cond_signal(
&flag);    /* raise the flag */
    printf(
"COUNT: unlocking box ");
    pthread_mutex_unlock(
&lock);    /* release the mailbox */
    
return NULL;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值