生产者消费者模型

                                                                                                        生产者消费者
生产者消费者模型的描述:两个进程共享一个缓冲区,一个进程称为生产者向缓冲区中放数据,另一个称为消费者从缓冲取中取数据,当缓冲区中被放时,生产者进程就必须进入挂起状态,直到消费者从缓冲中取走数据时,生产者才能继续向缓冲区中存放数据,同样当缓冲中取没有数据时,消费者进程就必须进入挂起休眠状态,直到生产者向缓冲区中放入数据时,消费者才能被唤醒继续从缓冲区中取走数据。
 生产者和消费者模型原则:
(1)一个交易场所 :(内存中具有存储数据的一段有界缓冲区)
(2)两种角色:(生产者,消费者);
(3)三种关系:
生产者---生产者:互斥
消费者--消费者:互斥
生产者--消费者:互斥与同步
//链表实现
#include<stdio.h>
#include<pthread.h>
#include <semaphore.h>
#include<stdlib.h>
//#define SIZE 10
typedef struct Node
{
int data;
struct Node* next;
}Node,**ppNode;
static pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
Node* pHead=NULL;
Node* GetNode(int x)
{ Node* tmp=(Node*)malloc(sizeof(Node));
if(tmp==NULL)
{
   perror("malloc");
return NULL;
}
tmp->data=x;
tmp->next=NULL;
return tmp;
}
void InitList(ppNode p)
{
*p=GetNode(0);
}
void PushFront(Node* pHead,const int x)
{
Node* tmp=GetNode(x);
tmp->next=pHead->next;
    pHead->next=tmp;
}
void PopFront(Node* pHead,int* out)
{
Node* tmp=pHead->next;
if(tmp)
{
Node* next=tmp->next;
pHead->next=next;
*out=tmp->data;
free(tmp);
tmp=NULL;
}
}
void* product(void* arg)
{
while(1)
{
int data=rand()%1000;
pthread_mutex_lock(&lock);
PushFront(pHead,data);
pthread_mutex_unlock(&lock);
pthread_cond_signal(&cond);
printf("product done:%d\n",data);
sleep(1);
}
}
void* consume(void* arg)
{
while(1)
{
int  c=-1;
pthread_mutex_lock(&lock);
while(pHead->next==NULL)
{
   printf("consume is waiting!\n");
pthread_cond_wait(&cond,&lock);
}
PopFront(pHead,&c);
pthread_mutex_unlock(&lock);
printf("consume is done: %d\n",c);
}
}
int main()
{
InitList(&pHead);
pthread_t p;
pthread_t c;
pthread_create(&p,NULL,product,NULL);
pthread_create(&c,NULL,consume,NULL);
pthread_join(p,NULL);
pthread_join(c,NULL);
pthread_mutex_destroy(&lock);
pthread_cond_destroy(&cond);
return 0;
}




 环形队列实现原理图:

环形队列实现规则:
(1)生产者优先:其实就算消费者优先,由于刚开始没有生产出数据,消费者也会被挂起;
(2)消费者永远不能追上消费者:试想一下如果消费者追上生产者或者超过消费者的时候,此时消费者消费的并不是生产者实际所生产出的数据,而属于垃圾数据;
(3)生产者不能将消费者包一圈:这个也很好理解,如果生产者允许将消费者包一圈的话,那就相当于生产者可以无限的生产,并不停的覆盖掉原来所产生的数据,那么如果原来生产出的数据中如果有的是消费者需要获取的数据,那么除了生产者在次生产出该数据外,消费者将再也不能得到所想要的数据;
//环形队列实现代码:
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
#define  SIZE 10
int Ring[SIZE]={0};
sem_t DataSem;  //数据信号量
sem_t BlankSem;   //空格信号量
void* consume(void* arg)
{
    int i=0;
    int data;
    while(1)
    {
       sem_wait(&DataSem);  //阻塞等待
      data= Ring[i++];
        sem_post(&BlankSem);
        i%=SIZE;
        printf("consume: %d\n",data);
        sleep(1);

    }
}
void* product(void* arg)
{
    int i=0;
    int data;
    while(1)
    {
        sem_wait(&BlankSem);
        Ring[i++]=data;
        sem_post(&DataSem);
        printf("product: %d\n",data++);
        i%=SIZE;
    }
   // sleep(1);
}
int main()
{
    pthread_t p,c;
    sem_init(&BlankSem,0,SIZE);
    sem_init(&DataSem,0,0);
    pthread_create(&c,NULL,consume,NULL);
    pthread_create(&p,NULL,product,NULL);
    pthread_join(c,NULL);
    pthread_join(p,NULL);
    sem_destroy(&BlankSem);
    sem_destroy(&DataSem);
    return 0;

}




//多线程版本实现
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
#define  SIZE 10
int Ring[SIZE]={0};
sem_t DataSem;  //数据信号量
sem_t BlankSem;   //空格信号量
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
void* consume(void* arg)
{
  static  int i=0;
    int data;
    while(1)
    {
       sem_wait(&DataSem);  //阻塞等待
      pthread_mutex_lock(&mutex);
      data= Ring[i++];
        sem_post(&BlankSem);
        i%=SIZE;
        printf("consume: %d\n",data);
        pthread_mutex_unlock(&mutex);
        sleep(1);

    }
}
void* product(void* arg)
{
    int i=0;
    int data;
    while(1)
    {
        sem_wait(&BlankSem);
        pthread_mutex_lock(&mutex);
        Ring[i++]=data;
        sem_post(&DataSem);
        printf("product: %d\n",data++);
        i%=SIZE;
        pthread_mutex_unlock(&mutex);
    sleep(2);
    }
}
int main()
{
    pthread_t p1,p2,c1,c2;
    sem_init(&BlankSem,0,SIZE);
    sem_init(&DataSem,0,0);
    pthread_create(&c1,NULL,consume,NULL);
    pthread_create(&c2,NULL,consume,NULL);
    pthread_create(&p1,NULL,product,NULL);
    pthread_create(&p2,NULL,product,NULL);
    pthread_join(c1,NULL);
    pthread_join(c2,NULL);
    pthread_join(p1,NULL);
    pthread_join(p2,NULL);
    sem_destroy(&BlankSem);
    sem_destroy(&DataSem);
    return 0;

}





















  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值