生产者消费者模型

时间:2021-08-07 17:42:20
                                                                                                        生产者消费者 生产者消费者模型的描述:两个进程共享一个缓冲区,一个进程称为生产者向缓冲区中放数据,另一个称为消费者从缓冲取中取数据,当缓冲区中被放时,生产者进程就必须进入挂起状态,直到消费者从缓冲中取走数据时,生产者才能继续向缓冲区中存放数据,同样当缓冲中取没有数据时,消费者进程就必须进入挂起休眠状态,直到生产者向缓冲区中放入数据时,消费者才能被唤醒继续从缓冲区中取走数据。  生产者和消费者模型原则: (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;

}


生产者消费者模型