生产者消费者问题

/* 生产者消费者问题*/

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#include<semaphore.h>

#define N 10	/* 定义10个缓冲数*/
#define M 5		/* 定义5个消费者和5个生产者*/

int in = 0;		/* 生产者标号*/
int out = 0;	/* 消费者标号*/

int buff[N] = {0};	/* 缓冲数目做初始化,开始时没产品*/

sem_t empty_sem;	/* 置空信号量,当缓冲为空,阻止消费者消费*/
sem_t full_sem;		/* 置满信号量,当缓冲为满,阻止生产者生产*/
pthread_mutex_t mutex; /* 互斥信号量,一次只有一个线程访问缓冲*/

int product_id = 0; /* 定义生产者id*/
int consumer_id = 0;/* 定义消费者id*/

/* 打印缓冲情况*/
void print()
{
	int i;
	for(i=0; i<N; i++)
		printf("%d ", buff[i]);
	printf("\n");
}

/* 生产者方法*/
void *produce()
{
	int id = product_id++;
	while(1)
	{/* 用sleep函数调节生产与消费的速度*/
		sleep(2);
		sem_wait(&full_sem); /* 如果生产满了,等待*/
		/* 为临界区加锁*/
		pthread_mutex_lock(&mutex);

		  in = in % N;
		  printf("product%d in No.%d, like: \t", id, in);

		  buff[in] = 1;
		  print();
		  in ++;
		/* 为临界区解锁*/
		pthread_mutex_unlock(&mutex);
		sem_post(&empty_sem);/* 空信号量位移1*/
	}
}

/* 消费者方法*/
void *consume()
{
	int id = consumer_id++;
	while(1)
	{
		sleep(1);

		sem_wait(&empty_sem);/* 如果消费空了,等待*/
		pthread_mutex_lock(&mutex);
		  
		  out = out % N;
		  printf("consumer%d in No.%d, like: \t", id, out);

		  buff[out] = 0;
		  print();
		  out++;
		pthread_mutex_unlock(&mutex);
		sem_post(&full_sem);/* 满信号量位移1*/
	}
}

int main()
{
	pthread_t product_id[M];
	pthread_t consumer_id[M];
	int i;
	int trd[M];

	/* 初始化同步信号量*/
	/* int sem_init(sem_t *sem, int pshared, unsigned int value);  
	 * sem_init() 初始化一个定位在 sem 的匿名信号量。
	 * value 参数指定信号量的初始值。 
	 * pshared 参数指明信号量是由进程内线程共享,还是由进程之间共享。
	 * 如果 pshared 的值为 0,那么信号量将被进程内的线程共享,并且应该放置在所有线程都可见的地址上(如全局变量,或者堆上动态分配的变量)。
	 * sem_init() 成功时返回 0;错误时,返回 -1,并把 errno 设置为合适的值。
	 */
	int init1 = sem_init(&full_sem, 0, N);
	int init2 = sem_init(&empty_sem, 0, 0);
	if(init1 && init2 != 0)
	{
		printf("sem init failed \n");
		exit(1);
	}
	/* 初始化互斥信号量*/
	int init3 = pthread_mutex_init(&mutex, NULL);
	if(init3 != 0)
	{
		printf("mutex init failed \n");
		exit(1);
	}
	/* 创建M个生产者线程*/	
	/* int pthread_create(pthread_t*restrict tidp,const pthread_attr_t *restrict_attr,void*(*start_rtn)(void*),void *restrict arg);
	 * 第一个参数为指向线程标识符的指针。
	 * 第二个参数用来设置线程属性。
	 * 第三个参数是线程运行函数的起始地址。
	 * 最后一个参数是运行函数的参数。
	 */
	for(i=0; i<M; i++)
	{
		trd[i] = pthread_create(&product_id[i], NULL, produce, (void *)(&i));
		if(trd[i] != 0)
		{
			printf("prduct%d creation failed \n", i);
			exit(1);
		}
	}
	/* 创建M个消费者线程*/
	for(i=0; i<M; i++)
	{
		trd[i] = pthread_create(&consumer_id[i], NULL, consume, (void *)(&i));
		if(trd[i] != 0)
		{
			printf("consumer%d creation failed \n", i);
			exit(1);
		}
	}
	/* 销毁线程*/
	for(i=0; i<M; i++)
	{
		pthread_join(product_id[i], NULL);
		pthread_join(consumer_id[i], NULL);
	}

	exit(0);
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值