关闭

Linux 线程示例

753人阅读 评论(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

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:65427次
    • 积分:1086
    • 等级:
    • 排名:千里之外
    • 原创:32篇
    • 转载:23篇
    • 译文:0篇
    • 评论:4条
    文章分类
    最新评论