1、生产者与消费者问题
空间满:生产者不能生产数据;
空间空:消费者不能取出数据;
在这种模型下,将会有(生产者:消费者)为:一对一、一对多、多对一、多对多。
为了简化问题,在这里就只实现一个生产者和一个消费者的问题。
模型如下
注意:
(1)、线程阻塞时,用条件变量来解决。唤醒并运行其后的语句是在遇到阻塞之后;
(2)、临界区模式;
pthread_mutex_lock(&mutex);
//临界区
pthread_cond_wait(&cond, &mutex); //该函数将自动解锁,此处将会发生阻塞。
......
pthread_mutex_unlock(&mutex);
(3)、本题还可以采用双缓冲区;
2、代码实现
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<pthread.h>
#define BUF_SIZE 8 //一个开辟8个数组元素空间
#define MAX_NUM 20 //将一共产生20个数据
struct PC{ //生产者与消费者结构体
pthread_mutex_t mutex; //互斥量
pthread_cond_t noempty; //条件变量,数组不空
pthread_cond_t nofull; //条件变量,数组不满
int buf[BUF_SIZE]; //开辟空间
int nput; //数组下标
int nval; //要存放的数据
int size; //统计当前数组空间大小
}shared = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER};
void* producer(void *arg){
for(;;){
pthread_mutex_lock(&shared.mutex);
if(shared.nval > MAX_NUM){
pthread_mutex_unlock(&shared.mutex);
break;
}
shared.buf[shared.nput] = shared.nval;
shared.nput++;
shared.nval++;
shared.size++;
if(shared.nput >= BUF_SIZE){
shared.nput = 0; //下标始终在0-7
}
if(shared.size >= BUF_SIZE){
pthread_cond_wait(&shared.nofull, &shared.mutex);
}else{
pthread_cond_signal(&shared.noempty);
}
pthread_mutex_unlock(&shared.mutex);
}
}
void *customer(void *arg){
int value;
int i = 0;
for(;;){
pthread_mutex_lock(&shared.mutex);
value = shared.buf[i];
i++;
printf("value = %d\n", value);
if(value >= MAX_NUM){
pthread_mutex_unlock(&shared.mutex);
break;
}
sleep(1);
if(i >= BUF_SIZE){
i = 0;
}
shared.size--;
if(shared.size == 0){
pthread_cond_wait(&shared.noempty, &shared.mutex);
}else{
pthread_cond_signal(&shared.nofull);
}
pthread_mutex_unlock(&shared.mutex);
}
}
void initPc(void){ //对结构体成员初始化
memset(shared.buf, 0, BUF_SIZE);
shared.nput = 0; //下标从0开始
shared.nval = 1; //存放的数据从1开始
shared.size = 0; //数组空间大小为0
}
int main(void){
initPc();
pthread_t pid, cid;
pthread_create(&pid, NULL, producer, NULL);
pthread_create(&cid, NULL, customer, NULL);
pthread_join(pid, NULL);
pthread_join(cid, NULL);
return 0;
}
运行结果
对以上的代码模式解读:首先是生产者生产,在空间满了之后,阻塞等待,此时,消费者在读取数据,等到读取为空的时候,唤醒生产者生产,最后,在生产完了的时候,消费者读取完成,将一起退出for循环。
这里的同步就是利用了锁机制完成的(通过互斥量和条件变量)。
转载于:https://blog.51cto.com/wait0804/1855228