/* 生产者消费者问题*/
#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);
}
生产者消费者问题
最新推荐文章于 2020-04-25 14:27:48 发布