生产者消费者模型

xiaoxiao2021-02-28  113

生产者消费者 生产者消费者模型的描述:两个进程共享一个缓冲区,一个进程称为生产者向缓冲区中放数据,另一个称为消费者从缓冲取中取数据,当缓冲区中被放时,生产者进程就必须进入挂起状态,直到消费者从缓冲中取走数据时,生产者才能继续向缓冲区中存放数据,同样当缓冲中取没有数据时,消费者进程就必须进入挂起休眠状态,直到生产者向缓冲区中放入数据时,消费者才能被唤醒继续从缓冲区中取走数据。  生产者和消费者模型原则: (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()00; 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; }
转载请注明原文地址: https://www.6miu.com/read-63881.html

最新回复(0)