生产者消费者模型可以被称为“三二一原则”
“三”是指有三个原则,这三个原则分别是:
(1)生产者与生产者之间是互斥的关系。
(2)生产者与消费者之间是同步与互斥关系。
(3)消费者与消费者是互斥的关系。
“二”是指两种角色:生产者和消费者
“一”是指一个交易场所
基于单链表实现的生产者与消费者模型:
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
typedef struct Listnode{
int data;
struct Listnode *next;
}node,*pnode,**ppnode;
pnode head = NULL;
pthread_mutex_t lock =PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond =PTHREAD_COND_INITIALIZER;
static pnode AllocListnode(int data)
{
pnode tmp = (pnode)malloc(sizeof(node));
if(tmp ==NULL)
{
perror("malloc");
exit(1);
}
tmp->data = data;
tmp->next = NULL;
}
static void DeleteListnode(pnode n)
{
if(n){
free(n);
}
}
void InitList(ppnode node)
{
*node = AllocListnode(0);
}
void PushFront(pnode node,int data)
{
pnode tmp = AllocListnode(data);
tmp->next = node->next;
node->next = tmp;
}
void PopFront(pnode node,int *out)
{
if(!Empty(node))
{
pnode tmp = node->next;
node->next = tmp->next;
*out = tmp->data;
DeleteListnode(tmp);
}
}
void ShowList(pnode node)
{
pnode start = node->next;
while(start)
{
printf("%d",start->data);
start = start->next;
}
printf("\n");
}
void Destory(pnode node)
{
int tmp = 0;
while(!Empty(node))
{
PopFront(node,&tmp);
}
DeleteListnode(node);
}
int Empty(pnode node)
{
return node->next ==NULL? 1:0;
}
//消费者
void *Consum(void *arg)
{
int c;
while(1)
{
c = -1;
//加锁
pthread_mutex_lock(&lock);
//如果为空等待
while(Empty(head))
{
printf("consum begin waiting...\n");
//条件变量等待
pthread_cond_wait(&cond,&lock);
}
PopFront(head,&c);
pthread_mutex_unlock(&lock);
printf("consum done: %d \n",c);
// sleep(3);
}
}
//生产者
void *Product(void *arg)
{
int p;
while(1)
{
p = rand()%1234;
pthread_mutex_lock(&lock);
PushFront(head,p);
pthread_mutex_unlock(&lock);
//生产完了给消费者信号
pthread_cond_signal(&cond);
printf("product done: %d\n",p);
sleep(3);
}
}
int main()
{
//初始化链表
InitList(&head);
//创建生产者和消费者线程
pthread_t P,C;
pthread_create(&P,NULL,Product,NULL);
pthread_create(&C,NULL,Consum,NULL);
pthread_join(C,NULL);
pthread_join(P,NULL);
pthread_mutex_destroy(&lock);
pthread_cond_destroy(&cond);
//销毁链表
Destory(head);
return 0;
}
基于环形队列的生产者消费者模型
必须满足 的条件
消费者必须紧跟在生产者的后面(不能超过)
生产者不能给 消费者套圈
生产者和消费者不能在同一个格子
如果为满 : 消费者先跑
如果为空: 生产者先跑
基于环形队列的生产者与消费者模型:
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#define SIZE 64
int ring[SIZE];
sem_t blank_sem;
sem_t data_sem;
pthread_mutex_t lock1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t lock2 = PTHREAD_MUTEX_INITIALIZER;
void *Product1(void *arg)
{
int step = 0;
int data = 0;
while(1)
{
pthread_mutex_lock(&lock1);
sem_wait(&blank_sem);
ring[step++] = data;
sem_post(&data_sem);
pthread_mutex_unlock(&lock1);
step %= SIZE;
printf("Product1 done: %d\n",data++);
sleep(3);
}
}
void *Product2(void *arg)
{
int step = 0;
int data = 0;
while(1)
{
pthread_mutex_lock(&lock1);
sem_wait(&blank_sem);
ring[step++] = data;
sem_post(&data_sem);
pthread_mutex_unlock(&lock1);
step %= SIZE;
printf("Product2 done: %d\n",data++);
sleep(3);
}
}
void *Comsum1(void *arg)
{
int step = 0;
while(1)
{
sleep(1);
pthread_mutex_lock(&lock2);
sem_wait(&data_sem);
int data = ring[step++];
sem_post(&blank_sem);
pthread_mutex_unlock(&lock2);
//环形
step %= SIZE;
printf("Comsum1 done :%d\n",data);
}
}
void *Comsum2(void *arg)
{
int step = 0;
while(1)
{
sleep(1);
pthread_mutex_lock(&lock2);
sem_wait(&data_sem);
int data = ring[step++];
sem_post(&blank_sem);
pthread_mutex_unlock(&lock2);
//环形
step %= SIZE;
printf("Comsum2 done :%d\n",data);
}
}
int main()
{
sem_init(&blank_sem,0,SIZE);
sem_init(&data_sem,0,0);
pthread_t P1,P2, C1,C2;
pthread_create(&P1,NULL,Product1,NULL);
pthread_create(&P2,NULL,Product2,NULL);
pthread_create(&C1,NULL,Comsum1,NULL);
pthread_create(&C2,NULL,Comsum2,NULL);
pthread_join(P1,NULL);
pthread_join(P2,NULL);
pthread_join(C1,NULL);
pthread_join(C2,NULL);
sem_destroy(&blank_sem);
sem_destroy(&data_sem);
return 0;
}