生产者消费者算法的简单实现

系列文章目录



实验内容

1.问题描述:一组生产者向一组消费者提供消息,它们共享一个有界缓冲池,生产者向其中投放消息,消费者从中取得消息。假定这些生产者和消费者互相等效,只要缓冲池未满,生产者可将消息送入缓冲池,只要缓冲池未空,消费者可从缓冲池取走一个消息。

2.功能要求:根据进程同步机制,编写一个解决上述问题的程序,可显示缓冲池状态、放数据、取数据等过程。

背景知识

1.了解经典同步问题“生产者和消费者

生产者与消费者可以通过一个环形缓冲池联系起来,环形缓冲池由几个大小相等的缓冲块组成,每个缓冲块容纳一个产品.每个生产者可不断地每次往缓冲池中送一个生产产品,而每个消费者则可每次从缓冲池中取出一个产品.
分析和理解
(1)既存在合作同步问题,也存在临界区互斥问题
合作同步:当缓冲池全满时,表示供过于求,生产者必须等待,同时唤醒消费者;当缓冲池全空时,表示供不应求,消费者应等待,同时唤醒生产者。互斥:缓冲池显然是临界资源,所在生产者与消费都要使用它,而且都要改变它的状态.
(2)基于环形缓冲区的生产者与消费者关系形式描述:公用信号量mutex:初值为1,用于实现临界区互斥生产者私用信号量empty

思路

用C++设计一个生产者和消费者在同一个进程地址空间内执行的两个进程,生产者生产物品,消费者消费物品,然后将物品放置在一个空缓冲区中供消费者消费。消费者从缓冲区中获得物品,然后释放缓冲区。

同时设置一个互斥信号量,用以阻止生产者线程和消费者进程同时操作缓冲区;还设置了一个信号量,当生产者生产出一个物品时可以用它向消费者发出信号;
另一个信号量,消费者释放出一个空缓冲区时可以用它向生产者发出信号;

并且分别独立设置了将数据放人缓冲区和从缓冲区取出数据的操作,让生产者消费者两个函数设计起来更简洁

这里要注意的是:缓冲区满时不能生产,缓冲区空时不能消费

————————————————

二、源代码

代码如下(示例):

#include <stdio.h>
#include <windows.h>
#include<iostream>
using namespace std;
#define N 5
typedef int semaphore;  
 semaphore mutex=1;     //互斥访问的信号量 
 semaphore empty=N;     //记录缓冲区中空的数量 
 semaphore full=0;      //记录录缓冲区中满的数量 
 semaphore buff[N];      //有N个槽数的缓冲区buf[N]
 semaphore in=0, out=0;  
 
  void p(semaphore *x)  //递减操作
 { *x=(*x)-1;}
 
 void v(semaphore *y)   // 递加操作
 {  *y=(*y)+1;}
 
  void produce_item(int *item)   //输入一个数,生产产品
 {
    cin>>*item;
 }
 
 void enter_item(int x)       //将新生产的数据放入缓存区 
 {
    buff[in]=x;
   cout<<"输入了"<<buff[in]<<"到缓冲区 buff["<<in<<"]"<<endl;
    in=(in+1)%N;
 }
 
void remove_item(int *yy)  //将缓存区的数据取走 
{
     
    
    cout<<"从缓冲区buff["<<out<<"]"<<"取走"<< buff[out]<<endl;
    *yy=buff[out];
    buff[out]='k';      //k代表已空 
    cout<<"因此缓冲区buff["<<out<<"]"<<"已经变成空"<<endl; 
    
    out=(out+1)%N;
}

void consume_item(int y)
{
	cout<<"消费从缓冲区取出的产品"<<y<<endl;
    
}
 
void producer();
void consumer();
 
//生产者 
void producer()
{
    int item;
  
   {
        Sleep(1000);
        produce_item(&item);
        p(&empty);          //减空槽数 
        p(&mutex);          //进入临界区
        enter_item(item);   //将一个新的数据项放入缓冲区
        v(&mutex);          //离开临界区
        v(&full);           //递增满槽数 
        
        if(full==N)         //若缓冲区满的话,调用消费者进程 
       {
		cout<<"缓冲区已满,无法在生产物品,请先消费"<<endl;
            consumer();
   }
	}
}
 
//消费者 
void consumer()
{
    int get_item;
    
    
        Sleep(1000);
        
            p(&full);           //递减满槽数 
            p(&mutex);          //进入临界区 
            remove_item(&get_item); //从缓冲区中取走一个数据
            v(&mutex);          //离开临界区
            v(&empty);          //递增空槽数 
            consume_item(get_item); //对数据项进行消费操作 
           
    
 }
 
 //调用生产者-消费者进程实现进程间同步 
 int main()
{
	cout<<"*********************************"<<endl;
    cout<<"*欢迎使用生产者消费者系统系统*"<<endl;
    while(1) {
	
    cout<<"*请输入"<<endl;
    cout << "1.生产者"<<endl;
    cout << "2.消费者"<<endl; 
     int i=0;
	 cin>>i; 
	 if(i==1)
	 producer();
	 else{ 
	 if(empty==N)        //若缓冲区全空的话,则无法进行消费 
        cout<<"缓冲区已空,无法在消费物品,请先生产"<<endl;
    else   
	 consumer();
	 } 
	 
	 }
	 
    
    return 0;
}

运行结果

在这里插入图片描述

结论

简单实现了生产者消费者算法,实现了可显示缓冲池状态、放数据、取数据等过程。还是过于抽象了,如果能用进度条那种形式就更好了,但是能力暂时有限,只是实现了其中的算法思想,还需要继续改进学习。

  • 0
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值