#背景
自己在实现生产者-消费者问题的时候,发现网上的代码都是无限生产,不存在终止问题.但是如果使用无限生产的代码去改造成生产定量的代码就会出现bug,比如是无法退出,生产数不对,所以我自己写了一个基于linux c的参数控制生产定量与生产者消费者数目的简单程序,分享一下并记录.
#函数介绍
·pthread_cond_wait(&con1,&mutex);//等待条件变量 互斥锁解锁
· pthread_cond_broadcast(&con1);激活所有等待该条件变量的线程
·pthread_cond_signal(&con2);// 激活一个等待该条件变量的线程 调度顺序由内核决定
·pthread_create(&pc[i],NULL,consumer,NULL); //构造线程
·pthread_join(pc[i],&thread_result);// 等待子进程结束
#难点
要知道pthread_con_wait()无法获取条件变量会阻塞自己.那么当缓存区已满,生产者将会阻塞自己.线程是并发的,由内核调度,所以下一个有可能还是生产者,那么会出现当不止一个生产者阻塞.如果这时达到了生产上限,那么当生产者被唤醒,生产量会继续++,所以判断条件需要在循环内部加入.
当生产者生产产品期间消费者消耗了已有的所有产品,将会阻塞,由于并发性,那么有可能有不止一个线程阻塞,当此时最后一个生产者停止生产,只会唤醒其中的一个线程,其余线程还会继续阻塞,所以需要使用pthread_cond_broadcast()唤醒所有的消费者线程.
···
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <string.h>
pthread_mutex_t mutex;
pthread_cond_t con1;
pthread_cond_t con2;
int num=0;
int sum = 0;
int rum=0;
int n = 0;
#define Maxnum 5 //缓存区大小
int to_int(char *a)
{
int num = 0 ;
for (int i= 0; a[i]!='\0' ;i++ )
{
int b = (int)(a[i]-'0');
num = num*10+b;
}
return num;
}
void *producer(void *args)
{
while(sum<n)
{
pthread_mutex_lock(&mutex);
if(num>=5)
{
printf("当前无空地\n");
pthread_cond_wait(&con1,&mutex);//等待条件变量 互斥锁解锁 pthread_cond_broadcast()则激活所有等待线程
}
num++;
sum++;
if(sum>n)
{
pthread_mutex_unlock(&mutex);
break;
}
printf("P id :%ld and i print %d\n",pthread_self(),sum);
pthread_cond_signal(&con2);// 激活一个 pthread_cond_broadcast()则激活所有等待线程
pthread_mutex_unlock(&mutex);
}
pthread_cond_broadcast(&con2);
pthread_exit(NULL);
}
void *consumer(void *args)
{
while(rum<n)
{
pthread_mutex_lock(&mutex);
if(num<=0){
printf("当前无产品\n");
pthread_cond_wait(&con2,&mutex);
}
num--;
rum++;
if(rum>n)
{
pthread_mutex_unlock(&mutex);
break;
}
printf("C id :%ld and i print %d\n",pthread_self(),rum);
pthread_cond_signal(&con1);
pthread_mutex_unlock(&mutex);
}
pthread_exit(NULL);
}
int main(int argc ,char *argv[])
{
n = to_int (argv[1]);
pthread_t pp[10],pc[10];
int res;
void *thread_result;
for(int i = 0 ;i<to_int(argv[2]);i++ )
{
res =pthread_create(&pp[i],NULL,producer,NULL);
if(res !=0)
{
printf("error1\n") ;
}
}
for(int i =0;i< to_int(argv[3]) ;i++)
{
res =pthread_create(&pc[i],NULL,consumer,NULL);
if(res !=0)
{
printf("error3\n") ;
}
}
for (int i =0 ;i<to_int(argv[2]);i++)
{
res = pthread_join(pp[i],&thread_result);
}
for (int i =0 ;i<to_int(argv[3]);i++)
{
res = pthread_join(pc[i],&thread_result);
}
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&con1);
pthread_cond_destroy(&con2);
return 0;
}
···