生产者消费者问题
问题介绍
生产者生产产品,消费者消费产品,两者的资源存储在同一个资源池。
因此,问题来了,生产者生产商品需要在资源池的存储范围内;然而消费者消费的资源需要在资源池不为空的前提下。由于两者均会对资源池造成修改,为了保证统一性,因此,两者需要互斥访问,同时,生产者生产产品需要对生产数量资源进行更改,因此生产者也需要互斥访问。
ProCon.c 代码实现
#include <stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include <pthread.h>
#define N 100
#define true 1
#define producerNum 10
#define consumerNum 5
#define sleepTime 1000
//互斥信号量
typedef int semaphore;
typedef int item;
item buffer[N] = {0};
int in = 0;
int out = 0;
int proCount = 0;
//互斥访问资源池信号量mutex,互斥改变生产商品数量信号量proCmutex
semaphore mutex = 1, empty = N, full = 0, proCmutex = 1;
void * producer(void * a){
while(true){
//等待占用proCount资源
while(proCmutex <= 0);
//占有资源并改变资源后释放
proCmutex--;
proCount++;
printf("生产一个产品ID%d, 缓冲区位置为%d\n",proCount,in);
proCmutex++;
while(empty <= 0){
printf("缓冲区已满!\n");
}
empty--;
while(mutex <= 0);
mutex--;
buffer[in] = proCount;
in = (in + 1) % N;
mutex++;
full++;
sleep(sleepTime);
}
}
void * consumer(void *b){
while(true){
while(full <= 0){
printf("缓冲区为空!\n");
}
full--;
while(mutex <= 0);
mutex--;
//nextc存储消费的商品
int nextc = buffer[out];
//消费完将缓冲区设置为0
buffer[out] = 0;
out = (out + 1) % N;
mutex++;
empty++;
printf("\t\t\t\t消费一个产品ID%d,缓冲区位置为%d\n", nextc,out);
sleep(sleepTime);
}
}
int main()
{
//线程池,存放生产者和消费者的线程
pthread_t threadPool[producerNum+consumerNum];
int i;
//创建生产者进程放入线程池
for(i = 0; i < producerNum; i++){
//pthread_t表示线程ID ,unsigned long int
pthread_t temp;
if(pthread_create(&temp, NULL, producer, NULL) == -1){
printf("ERROR, fail to create producer%d\n", i);
exit(1);
}
threadPool[i] = temp;
}
//创建消费者进程放入线程池
for(i = 0; i < consumerNum; i++){
pthread_t temp;
if(pthread_create(&temp, NULL, consumer, NULL) == -1){
printf("ERROR, fail to create consumer%d\n", i);
exit(1);
}
threadPool[i+producerNum] = temp;
}
//运行线程池。
void * result;
for(i = 0; i < producerNum+consumerNum; i++){
if(pthread_join(threadPool[i], &result) == -1){
printf("fail to recollect\n");
exit(1);
}
}
return 0;
}
编译
gcc -pthread ProCon.c -o ProCon
运行
./ProCon
知识补充:
//创建线程池
pthread_t threadPool[poolNum];
//创建线程,(指向线程标识符的指针,设置线程属性,线程运行函数的起始地址,运行函数的参数)
pthread_create(&temp, NULL, producer, NULL);
//定义无类型指针。void *也可以无需强制类型转换地赋给其它类型的指针。因为“无类型”可以包容“有类型”,而“有类型”则不能包容“无类型”
void * result;