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
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值