生产者与消费者模型
生产者:生产数据的线程
消费者:使用数据的线程
仓库:临时存储数据的缓冲区(仓库解决生产、消费不匹配的问题)
可能产生的问题:
生产快于消费:仓库爆满,撑死
消费快于生产:仓库空虚,饿死
利用条件变量来解决以上问题:
当缓冲区满的时候,生产者睡入条件变量(full),并通知消费者全部醒了(empty)
当缓冲区空的时候,消费者睡入条件变量(empty),并通知生产者全部醒来(full)
应用:利用生产者消费者模型构建 线程池\数据池
了解:哲学家就餐问题
以下代码是基于生产者消费者,在仓库里使用的案例
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#define BUF_MAX 20
// 仓库
char buf[BUF_MAX];
// 仓库中数据的数量
int cnt = 0;
// 仓库满的条件变量
pthread_cond_t full = PTHREAD_COND_INITIALIZER;
// 仓库空的条件变量
pthread_cond_t empty = PTHREAD_COND_INITIALIZER;
// 访问仓库的互斥量
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
// 显示仓库情况
void show_buf(const char* who,const char* dir,char data)
{
for(int i=0; i<cnt; i++)
{
printf("%c ",buf[i]);
}
printf("%s %c %s\n",dir,data,who);
}
// 生产者线程函数
void* producer(void* arg)
{
for(;;)
{
// 加锁
pthread_mutex_lock(&mutex);
while(BUF_MAX <= cnt)
{
printf("满仓\n");
// 睡入满仓条件变量并解锁
pthread_cond_wait(&full,&mutex);
}
// 生产数据
char data = 'A' + rand()%26;
buf[cnt++] = data;
show_buf("生产者","<-",data);
// 解锁
pthread_mutex_unlock(&mutex);
// 仓库有数据 唤醒消费者
pthread_cond_signal(&empty);
usleep(rand()%10*100000);
}
}
// 消费者线程函数
void* consumer(void* arg)
{
for(;;)
{
// 加锁
pthread_mutex_lock(&mutex);
while(0 >= cnt)
{
printf("空仓\n");
// 睡入满仓条件变量并解锁
pthread_cond_wait(&empty,&mutex);
}
// 消费数据
char data = buf[--cnt];
show_buf("消费者","->",data);
// 解锁
pthread_mutex_unlock(&mutex);
// 仓库有空位置 唤醒生产者
pthread_cond_signal(&full);
usleep(rand()%10*100000);
}
}
int main(int argc,const char* argv[])
{
pthread_t tid[10];
for(int i=0; i<5; i++)
{
pthread_create(&tid[i],NULL,producer,NULL);
}
for(int i=5; i<10; i++)
{
pthread_create(&tid[i],NULL,consumer,NULL);
}
for(int i=0; i<10; i++)
{
pthread_join(tid[i],NULL);