生產者消費者問題
問題介紹
生產者生產產品,消費者消費產品,兩者的資源存儲在同一個資源池。
因此,問題來了,生產者生產商品需要在資源池的存儲範圍內;然而消費者消費的資源需要在資源池不爲空的前提下。由於兩者均會對資源池造成修改,爲了保證統一性,因此,兩者需要互斥訪問,同時,生產者生產產品需要對生產數量資源進行更改,因此生產者也需要互斥訪問。
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;