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