生产者—消费者模型

首先介绍下单个生产者和消费者模型

首先创建一个环,环分为无数格子,其规则是:

    消费者永远追不上生产者

    生产者永远追不上消费者,更别说套圈

  形成两类角色,一个环形buf

假设有n个格子    :生产者的范围是[n,0];

                              消费者的范围是[0,n];


首先编辑Makefile

ring.c

需要引入的头文件

生产者

消费者

主函数

运行结果;

现在实现多生产者、消费者

生产者-消费者模型是指:
1.  生产者进行生产将物品放入仓库,同一时间只能有一个生产者将物品放入仓库,如果仓库满,生产者等待。
2.  消费者从仓库中取出物品,同一时间只能有一个消费者取出物品,如果仓库空,消费者等待;
3.  生产者将物品放入仓库时消费者不能同时取;
4.  消费者取物品时生产者不能放入物品;

   互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。
   同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源,如“第一类读写者模型”。


          总之,就是生产者群体或消费者群体内部是互斥的,两个群体之间是同步的。
当只有一个生产者、消费者时,由于同一群体内部不需要互斥,所以只需在群体之间实 现同步即可。

#include <stdio.h>  
#include <stdlib.h>  
#include <unistd.h>  
#include <pthread.h>  
#include <semaphore.h>  
  
#define N 2   // 消费者或者生产者的数目  
#define M 10 // 缓冲数目  
  
int in = 0;   // 生产者放置产品的位置  
int out = 0; // 消费者取产品的位置  
  
int buff[M] = {0}; // 缓冲初始化为0, 开始时没有产品  
  
sem_t empty_sem; // 同步信号量, 当满了时阻止生产者放产品  
sem_t full_sem;   // 同步信号量, 当没产品时阻止消费者消费  
pthread_mutex_t mutex; // 互斥信号量, 一次只有一个线程访问缓冲  
  
int product_id = 0;   //生产者id  
int prochase_id = 0; //消费者id  
  
/* 打印缓冲情况 */  
void print()  
{  
int i;  
for(i = 0; i < M; i++)  
   printf("%d ", buff[i]);  
printf("/n");  
}  
  
/* 生产者方法 */  
void *product()  
{  
int id = ++product_id;  
  
while(1)  
{  
   // 用sleep的数量可以调节生产和消费的速度,便于观察  
   sleep(1);  
   //sleep(1);  
    
   sem_wait(&empty_sem);  
   pthread_mutex_lock(&mutex);  
    
   in = in % M;  
   printf("product%d in %d. like: /t", id, in);  
    
   buff[in] = 1;    
   print();    
   ++in;  
    
   pthread_mutex_unlock(&mutex);  
   sem_post(&full_sem);    
}  
}  
  
/* 消费者方法 */  
void *prochase()  
{  
int id = ++prochase_id;  
while(1)  
{  
   // 用sleep的数量可以调节生产和消费的速度,便于观察  
   sleep(1);  
//sleep(1);  
    
   sem_wait(&full_sem);  
   pthread_mutex_lock(&mutex);  
    
   out = out % M;  
   printf("prochase%d in %d. like: /t", id, out);  
    
   buff[out] = 0;  
   print();  
   ++out;  
    
   pthread_mutex_unlock(&mutex);  
   sem_post(&empty_sem);  
}  
}  
  
int main()  
{  
pthread_t id1[N];  
pthread_t id2[N];  
int i;  
int ret[N];  
  
// 初始化同步信号量  
int ini1 = sem_init(&empty_sem, 0, M);  
int ini2 = sem_init(&full_sem, 0, 0);    
if(ini1 && ini2 != 0)  
{  
   printf("sem init failed /n");  
   exit(1);  
}  
//初始化互斥信号量  
int ini3 = pthread_mutex_init(&mutex, NULL);  
if(ini3 != 0)  
{  
   printf("mutex init failed /n");  
   exit(1);  
}  
// 创建N个生产者线程  
for(i = 0; i < N; i++)  
{  
   ret[i] = pthread_create(&id1[i], NULL, product, (void *)(&i));  
   if(ret[i] != 0)  
   {  
    printf("product%d creation failed /n", i);  
    exit(1);  
   }  
}  
//创建N个消费者线程  
for(i = 0; i < N; i++)  
{  
   ret[i] = pthread_create(&id2[i], NULL, prochase, NULL);  
   if(ret[i] != 0)  
   {  
    printf("prochase%d creation failed /n", i);  
    exit(1);  
   }  
}  
//销毁线程  
for(i = 0; i < N; i++)  
{  
   pthread_join(id1[i],NULL);  
   pthread_join(id2[i],NULL);  
}  
exit(0);  
}  

这个程序容易出错误的就是设置同步信号量和互斥信号量的顺序出错, 如在生产者或者消费者方法中把互斥信号量放在同步信号量的外层. 这样在内层中某个sem_wait不一定能通过, 从而造成死锁现象.
在多个消费者和一个消费者的不同就是是否需要互斥锁。




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值