Linux多线程,生产者消费者算法和条件变量的使用

来源:互联网 发布:和还原精灵类似软件 编辑:程序博客网 时间:2024/03/28 17:26

接着上一篇博文,原来双线程,现在为了实现 暂停/继续 功能,又加了一个线程。第三线程使用条件信号量,当用户按下S键,第三线程将检测到,并且将ifpause置为1,然后输出线程将在if语句成立后被条件信号量cond阻塞。

此时第三线程依然运行。

当检测到按下R后,ifpause置为0,并且使用条件信号量唤醒输出线程。

全局采用生产者/消费者算法。保证输出线程和从文件读数字的线程相互合作正确。

第三线程调用的函数kbhit(),前面一堆语句是为了设置终端,以实现输入字符无回显。

#include<stdio.h>#include<unistd.h>#include<string.h>#include<stdlib.h>#include<pthread.h>#include<semaphore.h>#include <termios.h>#include <fcntl.h>void *kbhit();void *thread_function(void *arg);int worksize=10;//char workarea[worksize];char workarea[10];sem_t sem;sem_t full;sem_t empty;pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*初始化互斥锁*/pthread_cond_t cond = PTHREAD_COND_INITIALIZER;/*初始化条件变量*/int in=0,out=0;int ifpause=0;//0--can continue running 1--condition change! need pauseint main(){int res;FILE *fp;int ch;pthread_t a_thread,hit_thread;void *thread_result;/////////semaphore init////////res=sem_init(&sem,0,1);if(res!=0){perror("error:");exit(1);}res=sem_init(&full,0,0);if(res!=0){perror("error:");exit(1);}res=sem_init(&empty,0,worksize);if(res!=0){perror("error:");exit(1);}//(void)signal(SIG);/////////////kbhit//////////////res=pthread_create(&hit_thread,NULL,kbhit,NULL);if(res!=0){perror("error:");exit(1);}/////////creat thread///////////res=pthread_create(&a_thread,NULL,thread_function,NULL);if(res!=0){perror("error:");exit(1);}/////////open file/////////////if((fp=fopen("/home/mirage/Desktop/program/pie.txt","r"))==NULL)    {perror("error:");exit(1);}///////////producer-read from file////////////while(1){    sem_wait(&empty);    sem_wait(&sem);     //critical        if((ch=fgetc(fp))==EOF)            break;        workarea[in]=ch;        in=(in+1)%worksize;//    sem_post(&sem);    //no critical    sem_post(&full);}//whilesem_destroy(&sem);sem_destroy(&empty);sem_destroy(&full);pthread_mutex_destroy(&mutex);exit(0);}//main///////////consumer-output to terminal////////////void *thread_function(void *arg){    int ent=0;    printf("pie=:3.\n");    while(1)    {        sem_wait(&full);        sem_wait(&sem);     //critical        ///////////////////////        pthread_mutex_lock(&mutex);        if(ifpause==1)//need pause                    pthread_cond_wait(&cond,&mutex);/*条件满足,需要等待,阻塞输出进程,之后生产者进程将在sem_wait(&sem)阻塞。*/            pthread_mutex_unlock(&mutex);        //////////////////////            usleep(80000);            printf("%c",workarea[out]);            fflush(stdout);            ent++;            if(ent==10)                {printf("\n");ent=0;}            out=(out+1)%worksize;        sem_post(&sem);     //no critical        sem_post(&empty);    }//while}/////////////kbhit()//////////////////void *kbhit(){    struct termios oldt, newt;    int ch;    int oldf;    tcgetattr(STDIN_FILENO, &oldt);    newt = oldt;    newt.c_lflag &= ~(ICANON | ECHO);    tcsetattr(STDIN_FILENO, TCSANOW, &newt);    oldf = fcntl(STDIN_FILENO, F_GETFL, 0);    fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);    //ch = getchar();    //tcsetattr(STDIN_FILENO, TCSANOW, &oldt);    //fcntl(STDIN_FILENO, F_SETFL, oldf);    ////////////////////////    while(1){    usleep(20000);    ch=getchar();    pthread_mutex_lock(&mutex);/*锁住互斥量*/    if(ch=='s')        {ifpause=1;}    else if(ch=='r'&&ifpause==1)//already pause but need run             {  ifpause=0;        pthread_cond_signal(&cond);/*条件改变,发送信号,通知输出线程*/                      }        pthread_mutex_unlock(&mutex);/*解锁互斥量*/    ///////////////////////    }//while}




0 0