#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#define ERR_EXIT(m) \
do{ \
perror(m); \
exit(EXIT_FAILURE); \
}while(0)
#define CONSUMERS_COUNT 1 //消费者数量
#define PRODUCERS_COUNT 5 //生产者数量
#define BUFFSIZE 10 //缓冲区大小,仓库大小
int g_buffer[BUFFSIZE];//缓冲区
unsigned short in = 0;//生产初始存放位置
unsigned short out = 0;//消费取出的位置
unsigned short produce_id = 0; //正在生产的id从0开始
unsigned short consume_id = 0;//正在消费的ID从0开始
sem_t g_sem_full;//信号量,
sem_t g_sem_empty;//信号量
pthread_mutex_t g_mutex;//互斥量
pthread_t g_thread[CONSUMERS_COUNT+PRODUCERS_COUNT];//线程组
void* consume(void* arg)
{
int num = (int)arg;
int i;
while(1)
{
printf("%d wait buffer empty\n", num);//消费者线程等待仓库有产品
//等待信号量g_sem_empty不为0;则进行P操作,并信号量减1
sem_wait(&g_sem_empty);//等待一个空的信号量,如果不空可以消费
pthread_mutex_lock(&g_mutex);
//打印当前各个仓库状态
for(i=0; i<BUFFSIZE; i++)
{
printf("%02d",i);//仓库序号
if(g_buffer[i] ==-1)
printf("%s", "NULL");//仓库无东西
else
printf("%d", g_buffer[i]);//仓库产品id
if(i == out)//标明为消费位置
printf("\t<--consume");
printf("\n");
}
//那个线程正在消费那个产品
consume_id = g_buffer[out];
printf("%d begin consume product %d\n", num, consume_id);
g_buffer[out] = -1;
out = (out+1)%BUFFSIZE;//下一个消费位置,由于是环形缓冲区
printf("%d end consume product %d\n", num,consume_id);
pthread_mutex_unlock(&g_mutex);
sem_post(&g_sem_full);//V操作,消费完一个信号量,信号量加1
sleep(5);
}
return NULL;
}
void* produce(void* arg)
{
int num = (int)arg;
int i;
while(1)
{
printf("%d wait buffer full\n", num);//生产者线程等待仓库不满
//等待信号量g_sem_full不为0;则进行P操作,并信号量减1
sem_wait(&g_sem_full);//等待一个满的信号量,如果不满可以生产
//加锁,生产时其他线程不得访问
pthread_mutex_lock(&g_mutex);
//打印当前各个仓库状态
for(i=0; i<BUFFSIZE; i++)
{
printf("%02d",i);//仓库序号
if(g_buffer[i] ==-1)
printf("%s", "NULL");//仓库无东西
else
printf("%d", g_buffer[i]);//仓库产品id
if(i == in)//标明为生产位置
printf("\t<--produce");
printf("\n");
}
//那个线程生产那个产品
printf("%d begin produce product %d\n", num, produce_id);
g_buffer[in] = produce_id;
in = (in+1)%BUFFSIZE;//下一个生产位置,由于是环形缓冲区
printf("%d end produce product %d\n", num, produce_id++);
pthread_mutex_unlock(&g_mutex);//开锁
sem_post(&g_sem_empty);//V一个空的信号量,释放资源,信号量加1
sleep(1);
}
return NULL;
}
int main(void)
{
int i;
//初始化仓库元素为-1
for(i =0; i<BUFFSIZE;i++)
{
g_buffer[i] =-1;
}
sem_init(&g_sem_full, 0, BUFFSIZE);//初始化信号量,缓冲区现有空间,防止溢出
sem_init(&g_sem_empty, 0, 0);//初始化信号量,用于通知消费者有产品
pthread_mutex_init(&g_mutex, NULL);//初始化互斥量
//初始化线程
for(i=0; i<CONSUMERS_COUNT; i++)
{
pthread_create(&g_thread[i], NULL, consume, (void*)i);
}
for(i=0; i<PRODUCERS_COUNT; i++)
{
pthread_create(&g_thread[i+CONSUMERS_COUNT], NULL, produce, (void*)i);
}
//线程回收
for(i=0; i<PRODUCERS_COUNT+CONSUMERS_COUNT; i++)
{
pthread_join(&g_thread[i], NULL);
}
sem_destroy(&g_sem_full);//销毁信号量
sem_destroy(&g_sem_empty);//销毁信号量
pthread_mutex_destroy(&g_mutex);//销毁互斥锁
return 0;
}
Posix线程:生产者与消费者问题
最新推荐文章于 2022-03-21 21:02:18 发布