生产者(producer)和消费者(consumer)问题是并发处理中最常见的一类问题,是一个多线程同步问题的经典案例。
可以这样描述这个问题,有一个或者多个生产者产生某种类型的数据,并放置在固定大小的缓冲区中,一个消费者从缓冲区中取数据,每次取一项,系统必须保证对缓冲区的重复操作,任何时候,只有一个生产者或者消费者可以访问缓冲区;同时,消费者只能在缓冲区不为空的时候从缓冲区中读数据,生产者只能在缓冲区不为满的时候向缓冲区写入数据。
上面的问题总结起来有两点:
第一是缓冲区的互斥访问问题,任意时刻最多只能有一个线程访问缓冲区,linux下可以使用互斥量pthread_mutex_t对访问缓冲区的临界区代码进行保护。
第二是生产者和消费者对缓冲区访问的同步问题,生产者在缓冲区满时不能向缓冲区中写入数据,同时消费者在缓冲区空时不能读取数据。
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#include<semaphore.h>
#define PRODUCER_NUM 5
#define CONSUMER_NUM 5
#define POOL_SIZE 11
int pool[POOL_SIZE];
int head=0;
int rear=0;
sem_t room_sem;
sem_t product_sem;
pthread_mutex_t mutex;
void producer_fun(void *arg)
{
while (1)
{
sleep(1);
sem_wait(&room_sem);
pthread_mutex_lock(&mutex);
pool[rear] = 1;
rear = (rear + 1) % POOL_SIZE;
printf("producer %d write to pool\n", (int)arg);
printf("pool size is %d\n",(rear-head+POOL_SIZE)%POOL_SIZE);
pthread_mutex_unlock(&mutex);
sem_post(&product_sem);
}
}
void consumer_fun(void *arg)
{
while (1)
{
int data;
sleep(10);
sem_wait(&product_sem);
pthread_mutex_lock(&mutex);
data = pool[head];
head = (head + 1) % POOL_SIZE;
printf("consumer %d read from pool\n", (int)arg);
printf("pool size is %d\n",(rear-head+POOL_SIZE)%POOL_SIZE);
pthread_mutex_unlock(&mutex);
sem_post(&room_sem);
}
}
int main()
{
pthread_t producer_id[PRODUCER_NUM];
pthread_t consumer_id[CONSUMER_NUM];
pthread_mutex_init(&mutex, NULL);
int ret = sem_init(&room_sem, 0, POOL_SIZE-1);
if (ret != 0)
{
printf("sem_init error");
exit(0);
}
ret = sem_init(&product_sem, 0, 0);
if (ret != 0)
{
printf("sem_init error");
exit(0);
}
for (int i = 0; i < PRODUCER_NUM; i++)
{
ret =pthread_create(&producer_id[i], NULL, producer_fun, (void*)i);
if (ret != 0)
{
printf("producer_id error");
exit(0);
}
ret = pthread_create(&consumer_id[i], NULL, consumer_fun, (void*)i);
if (ret != 0)
{
printf("consumer_id error");
exit(0);
}
}
for(int i=0;i<PRODUCER_NUM;i++)
{
pthread_join(producer_id[i],NULL);
pthread_join(consumer_id[i],NULL);
}
exit(0);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)