生产者-消费者问题
1.1 整型信号量
1.1.1 Windows环境
直接运行如下代码即可
#include <stdio.h>
#include <pthread.h>//线程的创建
#include <windows.h>
#define N 100
#define true 1
#define producerNum 10
#define consumerNum 5
#define sleepTime 2000
typedef int semaphore;
typedef int item;
item buffer[N] = {0};
int in = 0;
int out = 0;
int proCount = 0;
semaphore mutex = 1, empty = N, full = 0;
//生产者
void * producer(void * a){
while(true){
while(mutex <= 0);//缓冲区位置不够,一直循环等待,S<=0不断【检测测试】
mutex--;//实现互斥的P操作【上锁】,缓冲区位置足够,占用一个位置资源
proCount++;//生产一个产品
printf("生产一个产品ID%d, 缓冲区位置为%d\n",proCount,in);
while(empty <= 0){
printf("缓冲区已满!\n");
}
empty--;//实现同步的P操作
buffer[in] = proCount;
in = (in + 1) % N;
mutex++;//实现互斥的V操作【开锁】
full++;//实现同步的V操作
Sleep(sleepTime);
}
}
//消费者
void * consumer(void *b){
while(true){
while(full <= 0){
printf("缓冲区为空!\n");
}
full--;//实现同步的P操作
while(mutex <= 0);
mutex--;//实现互斥的P操作【上锁】
int nextc = buffer[out];
buffer[out] = 0;//消费完将缓冲区设置为0
out = (out + 1) % N;
mutex++;//实现互斥的V操作【开锁】
empty++;//实现同步的V操作
printf("\t\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 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("ERROR: fail to recollect\n");
exit(1);
}
}//运行线程池
return 0;
}
运行结果部分截图如下:
1.1.2 Unix环境
1、代码如下
#include <stdio.h>
#include <pthread.h>//线程的创建
#define N 100
#define true 1
#define producerNum 10
#define consumerNum 5
typedef int semaphore;
typedef int item;
item buffer[N] = {0};
int in = 0;
int out = 0;
int proCount = 0;
semaphore mutex = 1, empty = N, full = 0;
//生产者
void * producer(void * a){
while(true){
while(mutex <= 0);//缓冲区位置不够,一直循环等待,S<=0不断【检测测试】
mutex--;//实现互斥的P操作【上锁】,缓冲区位置足够,占用一个位置资源
proCount++;//生产一个产品
printf("生产一个产品ID%d, 缓冲区位置为%d\n",proCount,in);
while(empty <= 0){
printf("缓冲区已满!\n");
}
empty--;//实现同步的P操作
buffer[in] = proCount;
in = (in + 1) % N;
mutex++;//实现互斥的V操作【开锁】
full++;//实现同步的V操作
}
}
//生产者
void * producer(void * a){
while(true){
while(mutex <= 0);//缓冲区位置不够,一直循环等待,S<=0不断【检测测试】
mutex--;//实现互斥的P操作【上锁】,缓冲区位置足够,占用一个位置资源
proCount++;//生产一个产品
printf("生产一个产品ID%d, 缓冲区位置为%d\n",proCount,in);
while(empty <= 0){
printf("缓冲区已满!\n");
}
empty--;//实现同步的P操作
buffer[in] = proCount;
in = (in + 1) % N;
mutex++;//实现互斥的V操作【开锁】
full++;//实现同步的V操作
Sleep(sleepTime);
}
}
//消费者
void * consumer(void *b){
while(true){
while(full <= 0){
printf("缓冲区为空!\n");
}
full--;//实现同步的P操作
while(mutex <= 0);
mutex--;//实现互斥的P操作【上锁】
int nextc = buffer[out];
buffer[out] = 0;//消费完将缓冲区设置为0
out = (out + 1) % N;
mutex++;//实现互斥的V操作【开锁】
empty++;//实现同步的V操作
printf("\t\t\t\t\t消费一个产品ID%d,缓冲区位置为%d\n", nextc,out);
}
}
//主函数
int main()
{
pthread_t threadPool[producerNum+consumerNum];//创建线程池
int i;
for(i = 0; i < producerNum; i++){
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("ERROR: fail to recollect\n");
exit(1);
}
}//运行线程池
return 0;
}
2、编译运行
错误编译:
~$ gcc -o fileName fileName.c
正确编译:
/*
注意:该程序为多线程程序
1、需要添加头文件#inlcude <pthread.h>才能创建线程
2、编译时需要手动连接pthread库
因为pthread不是Linux系统的默认库,而是POSIX线程库。连接时需要使用库libpthread.a。在代码中使用pthread_create、pthrea_join等时,在编译中要加-lpthread参数。在Linux中将其作为一个库来使用,因此加上 -lpthread(或-pthread)以显式链接该库。
*/
~$ gcc fileName.c -lpthread -o fileName //编译
~$ ./fileName //运行
运行结果部分截图如下:
1.2 记录型信号量
1、代码如下
#include <stdio.h>
#include <windows.h>
#include <unistd.h>
#define N 100
#define true 1
#define producerNum 10
#define consumerNum 5
#define sleepTime 2000
typedef struct{
int value;
struct process_control_block *list;
}semaphore;
void wait(semaphore *S){
S->value--;
if(S->value<0)block(S->list);
}
void signal(semaphore *S){
S->value++;
if(S->value<=0)wakeup(S->list);
}
typedef int item;
item buffer[N] = {0};
int in = 0;
int out = 0;
int proCount = 0;
semaphore *mutex,*empty,*full;
void* producer(){
int i = 0;
do{
wait(empty);
wait(mutex);
proCount++;
printf("生产一个产品ID%d,缓冲区位置为%d\n",proCount,in);
while(empty->value<=0){
printf("缓冲区已满!\n");
}
buffer[in] = proCount;
in = (in+1) % N;
signal(mutex);
signal(full);
Sleep(sleepTime);
}while(i<100);
}
void* consumer(){
int i=0;
do{
while(full->value <= 0){
printf("缓冲区为空!\n");
}
wait(full);
wait(mutex);
int nextc = buffer[out];
out = (out+1) % N;
signal(mutex);
signal(empty);
printf("\t\t\t\t\t消费一个产品ID%d,缓冲区位置为%d\n", nextc,out);
Sleep(sleepTime);
}while(i<15);
return NULL;
}
int main(){
mutex->value = 1;
empty->value = N;
full->value = 0;
producer();
consumer();
return 0;
}
问题:block和wakeup未实现
——by一宇 2020-01-04
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_45011621/article/details/112208338