C语言之 - 生产消费者模型

一、前言

生产消费者模型,主要考验的就是对互斥这部分的理解,下面就用了简单的例子来谈一谈经典的生产消费者模型。

二、用到的知识

sem_init(); // 初始化信号量
sem_wait(); // 信号量减一
sem_post(); // 信号量加一

三、工作模型

生产者每隔一段时间生产一个产品入库
消费者每隔一段时间消费一个产品出库
两者的工作时间不同

思路:
	生产者生产物品时,生产信号量减一
	生产过程加一
	生产完成后,消费信号量加一
	
	消费者消费时,消费信号减一
	消费过程减一
	消费完成后,生产信号加一

	出库入库的时候保证时互斥的。

四、代码实现

 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #include <semaphore.h>
 #include <pthread.h>
 
 #define msleep(x) usleep(x * 1000) // 延时
 #define PRODUCT_SPEED 200  // 生产速度
 #define COUSUM_SPEED  400  // 消费速度
 #define INIT_NUM  3// 仓库初始库存
 #define TOTAL_NUM 10   // 仓库总库存
 
 struct HANDLE
 {
 	sem_t p_sem; // 生产信号量
 	sem_t c_sem; // 消费信号量
 	sem_t sh_sem;// 出库入库信号量
 
 	pthread_t p_tid; // 生产者线程
 	pthread_t c_tid; // 消费着线程
 	
 	int num; // 仓库库存
 };
 
 /* 生产延时 */
 void productDelay(void)
 {
 	msleep(PRODUCT_SPEED * 10);
 }
 
 /* 消费延时延时 */
 void consumerDelay(void)
 {
 	msleep(COUSUM_SPEED * 10);
 }
 
 /* 消费出库 */
 void sub_to_work(struct HANDLE *handle)
 {
 	sem_wait(&(handle->sh_sem));
 	handle->num--;
 	msleep(300);
 	sem_post(&(handle->sh_sem));
 }
 
 /* 生产入库 */
 void add_to_work(struct HANDLE *handle)
 {
 	sem_wait(&(handle->sh_sem));
 	handle->num++;
 	msleep(300);
 	sem_post(&(handle->sh_sem));
 }
 
 /* 生产线程 */
 void *product(void *arg)
 {
 	struct HANDLE *handle = (struct HANDLE *)arg;
 	int num = 0;
 	while(1)
 	{
 		sem_wait(&(handle->p_sem));
 		productDelay();
 		add_to_work(handle);
 		printf("生产 num = %d\n", handle->num);
 		sem_post(&(handle->c_sem));
 	}
 	return NULL;
 }
 
 /* 消费线程 */
 void *consumer(void *arg)
 {
 	struct HANDLE *handle = (struct HANDLE *)arg;
 	int num = 0;
 	while(1)
 	{
 		sem_wait(&(handle->c_sem));
 		sub_to_work(handle);
 		printf("消费 num = %d\n", handle->num);
 		sem_post(&(handle->p_sem));
 		consumerDelay();
 	}
 	return NULL;
 }
 
 int main(int argc, char *argv[])
 {
 	struct HANDLE handle;
 	memset(&handle, 0x00, sizeof(struct HANDLE));
 	handle.num = INIT_NUM;
 
 	sem_init(&handle.p_sem,  0, TOTAL_NUM - INIT_NUM);
 	sem_init(&handle.c_sem,  0, INIT_NUM);
 	sem_init(&handle.sh_sem, 0, 1);
 
 	pthread_create(&(handle.p_tid), NULL, product,  (void *)(&handle));
 	pthread_create(&(handle.c_tid), NULL, consumer, (void *)(&handle));
 
 	pthread_join(handle.p_tid, NULL);
 	pthread_join(handle.c_tid, NULL);
 	
 	return 0;
 }

5、小结

生产消费模型在各种场景下还是比较常用的,要理解信号量的操作及生产消费模型。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值