生产者-消费者模型的两种实现方式

  本文主要来总结生产者-消费者模型的代码实现,至于其原理,请大家自行百度.

一、基于链表的生产-消费模型(条件变量)

  我们以链表为例,生产者进行头部插入,消费者进行头部删除,因此,先将链表相关操作封装为LinkList.h,具体代码如下:


//文件说明:LinkList.h
//作者:高小调
//创建时间:2017年06月27日 星期二 14时57分27秒
//开发环境:Kali Linux/g++ v6.3.0

#include<assert.h>
#include<stdlib.h>
#include<stdio.h>
//链表节点
typedef struct LinkListNode{
	int val;
	struct inkListNode *next;
}Node,*pNode,**ppNode;

//初始化链表
void InitLinkList(ppNode head){
	assert(head);
	*head = NULL;
}
//判断链表是否为空
int IsEmpty(pNode head){
	return head==NULL;
}
//申请新节点
pNode BuyNewNode(int val){
	pNode ret = (pNode)malloc(sizeof(Node));
	ret->val = val;
	ret->next = NULL;
	return ret;
}
//头插
void PushFront(ppNode head,int val){
	assert(head);
	if(*head==NULL){
		*head = BuyNewNode(val);
		return ;
	}
	pNode newNode = BuyNewNode(val);
	newNode->next = *head;
	*head = newNode;
}
//头删
void PopFront(ppNode head,int *val){
	assert(head);
	if((*head) == NULL){
		return ;
	}
	if((*head)->next == NULL){
		*val = (*head)->val;
		free(*head);
		*head = NULL;
		return ;
	}
	pNode del = *head;
	*head = del->next;
	*val = del->val;
	free(del);
}
//销毁链表
void Destory(ppNode head){
	assert(head);
	pNode cur = *head;
	pNode del = NULL;
	while(cur!=NULL){
		del = cur;
		cur = cur->next;
		free(del);
	}
	*head = NULL;
}
//打印链表
void PrintLinkList(pNode head){
	pNode cur = head;
	while(cur!=NULL){
		printf("%d ",cur->val);
		cur = cur->next;
	}
	printf("\n");
}

   然后进入我们线程的生产消费模型:


//文件说明:test.c
//作者:高小调
//创建时间:2017年06月27日 星期二 14时56分13秒
//开发环境:Kali Linux/g++ v6.3.0

#include<stdio.h>
#include<pthread.h>
#include"LinkList.h"
//互斥锁
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
//条件变量
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
//测试链表
void TestLinkList(){
	pNode head;
	InitLinkList(&head);
	int tmp;
	for(int i=0; i<10; ++i){
		PushFront(&head,i);
		PrintLinkList(head);
	}
	for(int i=0; i<10; ++i){
		PopFront(&head,&tmp);
		PrintLinkList(head);
	}
}
pNode head;
//生产者:每次向头节点插入数据
void *Productor(void*arg){
	int val = 0;
	while(1){
		//互斥锁加锁:确保生产时不会消费,消费时不会生产
		pthread_mutex_lock(&lock);
		val = rand()%100;
		PushFront(&head,val);
		printf("Productor push %d\n",val);
		//互斥锁解锁
		pthread_mutex_unlock(&lock);
		//条件变量,生产完成之后向消费者发出信号消费
		pthread_cond_signal(&cond);
		sleep(1);
	}
}
//消费者:每次将头节点数据取出
void *Consumer(void*arg){
	int val = 0;
	while(1){
		//互斥锁
		pthread_mutex_lock(&lock);
		while(head==NULL){
			//链表中没数据,阻塞等待生产者发消费信号
			printf("wait for data\n");
			pthread_cond_wait(&cond,&lock);
		}
		PopFront(&head,&val);
		printf("Consumer pop %d\n",val);
		pthread_mutex_unlock(&lock);
		sleep(1);
	}
}
int main(){
	InitLinkList(&head);
	pthread_t cid1,cid2;
	pthread_create(&cid1,NULL,Productor,NULL);
	pthread_create(&cid2,NULL,Consumer,NULL);
	pthread_join(&cid1,NULL);
	pthread_join(&cid2,NULL);
	
	return 0;
}

 二、基于环形队列的生产-消费模型(信号量)


//文件说明:test2.c
//作者:高小调
//创建时间:2017年06月27日 星期二 16时29分30秒
//开发环境:Kali Linux/g++ v6.3.0

#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
#include<stdlib.h>
#define SIZE 1024
//环形队列
int arr[SIZE] = {0};
sem_t sem_pro;		//描述环形队列中的空位置
sem_t sem_con;		//描述唤醒队列中的数据
//生产者,只要环形队列有空位,便不断生产
void*productor(void*arg){
	int data = 0;
	int proIndex = 0;
	while(1){
		//有空位便生产,没空位便阻塞等消费者消费
		sem_wait(&sem_pro);
		data = rand()%1234;
		arr[proIndex] = data;
		printf("product done %d\n",data);
		proIndex = (proIndex+1)%SIZE;
		//供消费者消费的数据加1
		sem_post(&sem_con);
	}
}
//消费者,只要环形队列中有数据,就不断消费
void*consumer(void*arg){
	int data = 0;
	int conIndex = 0;
	while(1){
		//环形队列中存在数据则消费,不存在数据则阻塞,直到有数据为止
		sem_wait(&sem_con);
		data = arr[conIndex];
		printf("consume done %d\n",data);
		conIndex = (conIndex+1)%SIZE;
		//最后,消费了一个数据,空位加1
		sem_post(&sem_pro);
	}
} 

int main(){
	pthread_t pro,con;
	sem_init(&sem_pro,0,SIZE-1);		//一开始有很多空位置
	sem_init(&sem_con,0,0);			//但并没有数据

	pthread_create(&pro,NULL,productor,NULL);
	pthread_create(&con,NULL,consumer,NULL);
	pthread_join(pro,NULL);
	pthread_join(con,NULL);

	sem_destroy(&sem_pro);
	sem_destroy(&sem_con);
	return 0;
}

 

转载于:https://www.cnblogs.com/caolicangzhu/p/7086176.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值