首页 > 代码库 > Linux多线程,生产者消费者算法和条件变量的使用

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

接着上一篇博文,原来双线程,现在为了实现 暂停/继续 功能,又加了一个线程。第三线程使用条件信号量,当用户按下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 pause
int 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);
}//while
sem_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
}


本文出自 “加菲猫吃铜锣烧” 博客,请务必保留此出处http://mirage1993.blog.51cto.com/2709744/1409440