C语言——生产者消费者问题

百度文献查看原文

核心代码:

#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<string.h>
#include<windows.h>
#define dataBufferSize  2        //缓冲区数目
#define processNum 4            //进程数量(生产者、消费者进程总数目)
typedef struct Seamphore          //信号量
{       
int value;            //信号量的值
int *pcq;            //信号量队列指针
} Seamphore;
int producerCongestionQueue[processNum];    //等待信号量empty的阻塞队列
int consumerCongestionQueue[processNum];    //等待信号量full的阻塞队列
int shareCongestionQueue[processNum];        //等待信号量mutex的阻塞队列
Seamphore empty={dataBufferSize,producerCongestionQueue}; // empty:空缓冲区数目
Seamphore full={0,consumerCongestionQueue};  // full:缓冲区内可用的产品
Seamphore mutex={1,shareCongestionQueue};    //mutex:互斥信号量
struct DataBuffer          //缓冲区
{           
int buffer[dataBufferSize];   
int count;                //当前产品数量
}dataBuffer;
typedef struct Process          //进程PCB
{
char name[10];                //进程名
int roleFlag;                    //进程类型(1: 生产者  0: 消费者)
int currentState;              //进程状态(1: 就绪态  0: 阻塞态)
int currentStep;              //断点
int data;                        //临时数据
int code;                        //进程编号
}Process;
Process process[processNum];    //进程集合
void moveDataForward()
{       
int i;
for (i = 0; i <dataBuffer.count; i++)
dataBuffer.buffer[i] = dataBuffer.buffer[i+1];
}
void push(int data)      //产品送入缓冲区
{           
dataBuffer.buffer[dataBuffer.count++] = data;
}
int pop()            //从缓冲区取出产品
{                       
int data = dataBuffer.buffer[0];
dataBuffer.count--;           
moveDataForward();
return data;
}
void initProcess() {            //初始化进程集合
int i;
char digitTemp[5];
srand(time(NULL));
for (i = 0; i <processNum; i++) {
process[i].roleFlag = rand()%2;            // 随机指定当前进程为生产者或消费者
if (process[i].roleFlag)
strcpy(process[i].name, "生产者");
else
strcpy(process[i].name, "消费者");
strcat(process[i].name, itoa(i+1, digitTemp, 10));
process[i].currentState = 1;
process[i].currentStep = 1;
process[i].code = i + 1;
producerCongestionQueue[i] = 0;
consumerCongestionQueue[i] = 0;
shareCongestionQueue[i] = 0;
}
}
void wakeup(int *pcq) {                    //唤醒进程
int code = pcq[0] - 1;                //取出队首进程
process[code].currentState = 1;        //进程置为就绪态
//当进程被唤醒后继续执行任务
if (process[code].roleFlag == 1) {        //生产者
if (process[code].currentStep == 2) {
printf("%20s: 该进程被唤醒!申请空缓冲区成功!\n", process[code].name);
} else if (process[code].currentStep == 3) {
printf("%20s: 该进程被唤醒!申请访问缓冲区成功!\n", process[code].name);
}
} else if (process[code].roleFlag == 0) {    //消费者
if (process[code].currentStep == 1) {
process[code].data = pop();
printf("%20s: 该进程被唤醒!申请取产品%d成功!\n", process[code].name, process[code].data);
} else if (process[code].currentStep == 2) {
printf("%20s: 该进程被唤醒!申请访问缓冲区成功!\n", process[code].name);
}       
}
process[code].currentStep++;
for (int i = 1; (i <processNum) && (pcq[i] != 0); i++) {        //删除队首进程
pcq[i-1] = pcq[i];
if (pcq[i-1] >processNum) {
pcq[i-1] = 0;
}
}  
}
void sleep(int pcq[], int code) {            //阻塞进程   
int i;
process[code-1].currentState = 0;            //进程置为阻塞态
for (i = 0; i <processNum; i++) {
if (!pcq[i]) {
pcq[i] = code;
break;
}
}
}
void P(Seamphore *s, Process *p) {                //模拟P操作
s->value -= 1;
if (s->value>= 0) {                       
if (p->roleFlag == 1) {                    //生产者
if (p->currentStep == 2) {
printf("%20s: 申请空缓冲区成功!\n", p->name);
} else if (p->currentStep == 3) {
printf("%20s: 申请访问缓冲区成功!\n", p->name);
}
} else if (p->roleFlag == 0) {            //消费者
if (p->currentStep == 1) {
printf("%20s: 申请取出产品成功!\n", p->name);
} else if (p->currentStep == 2) {
printf("%20s: 申请访问缓冲区成功!\n", p->name);
}
}       
p->currentStep++;                        //下一步
} else if (s->value < 0) {               
if (p->roleFlag == 1) {                    //生产者
if (p->currentStep == 2) {
printf("%20s: 无空缓冲区, 该进程被阻塞!\n", p->name);
} else if (p->currentStep == 3) {
printf("%20s: 其他进程正在访问缓冲区, 该进程被阻塞!\n", p->name);
}
} else if (p->roleFlag == 0) {            //消费者
if (p->currentStep == 1) {
printf("%20s: 无产品可取, 该进程被阻塞!\n", p->name);
} else if (p->currentStep == 2) {
printf("%20s: 其他进程正在访问缓冲区, 该进程被阻塞!\n", p->name);
}
}
sleep(s->pcq, p->code);        //阻塞进程       
}
}
void V(Seamphore *s, Process *p) {            //模拟V操作
s->value += 1;
if (p->roleFlag == 1) {                    //生产者
if (p->currentStep == 5) {
printf("%20s: 释放缓冲区访问权!\n", p->name);
} else if (p->currentStep == 6) {
printf("%20s: 产品已送入缓冲区,产品数量增加!\n", p->name);
}
} else if (p->roleFlag == 0) {            //消费者
if (p->currentStep == 4) {
printf("%20s: 释放缓冲区访问权!\n", p->name);
} else if (p->currentStep == 5) {
printf("%20s: 产品已取出,空缓冲区数量增加!\n", p->name);
}
}
if (s->value<= 0) {
wakeup(s->pcq);       
}
p->currentStep++;           
}
void produce(Process *p) {            //模拟生产者进程
switch (p->currentStep) {
case 1:                                                            //1 生产产品
p->data = rand()%1000;
printf("%20s: 生产一个产品%d!\n", p->name, p->data);
p->currentStep++;
break;
case 2:                                                            //2 申请空缓冲区
P(&empty, p);
break;
case 3:                                                            //3 申请访问缓冲区
P(&mutex, p);
break;
case 4:                                                            //4 将产品送入缓冲区
push(p->data);
printf("%20s: 将产品%d正送入缓冲区!\n", p->name, p->data);
p->currentStep++;
break;
case 5:                                                            //5 释放缓冲区访问权
V(&mutex, p);
break;
case 6:                                                            //6 产品已送入缓冲区,产品数量加1
V(&full, p);
p->currentStep = 1;
break;
}
}
void consume(Process *p) {                //模拟消费者进程
switch (p->currentStep) {
case 1:                                                            //1 申请从缓冲区取出产品
P(&full, p);
break;
case 2:                                                            //2 申请访问缓冲区
P(&mutex, p);
break;
case 3:                                                            //3 从缓冲区中取出产品
p->data = pop();
printf("%20s: 从缓冲区中正取出产品%d!\n", p->name, p->data);
p->currentStep++;
break;
case 4:                                                            //4 释放缓冲区访问权
V(&mutex, p);
break;
case 5:                                                    //5 已从缓冲区取出一个产品,空缓冲区数量加1
V(&empty, p);
break;
case 6:                                                            //6 消费产品
printf("%20s: 消费产品%d!\n", p->name, p->data);
p->currentStep = 1;
break;
}
}
void rr() {            //模拟进程调度
Process *p;
while(1) {
p = &process[rand()%processNum];        //随机选取进程集合内某一进程
if (!p->currentState) {                    //选取的进程若为阻塞态,重新选取其它可执行进程
continue;
}
if (p->roleFlag) {            //1: 生产者  0: 消费者
produce(p);
} else {
consume(p);
}   
Sleep(100);
}
}
void deal() {
printf("\t\t生产者消费者算法模拟\n\n");
initProcess();
rr();
}
int main () {
deal();
return 0;
}

下面是一个简单的生产者-消费者问题的C语言代码实现: ```c #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <unistd.h> #define BUFFER_SIZE 10 int buffer[BUFFER_SIZE]; // 缓冲区数组 int counter = 0; // 缓冲区计数器 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // 互斥锁 pthread_cond_t full = PTHREAD_COND_INITIALIZER; // 缓冲区满条件变量 pthread_cond_t empty = PTHREAD_COND_INITIALIZER; // 缓冲区空条件变量 void *producer(void *arg) { int val; while (1) { val = rand() % 100; // 随机生成数值 pthread_mutex_lock(&mutex); while (counter == BUFFER_SIZE) // 缓冲区满,等待空闲空间 pthread_cond_wait(&empty, &mutex); buffer[counter++] = val; // 放入缓冲区 printf("生产者:%d,缓冲区大小:%d\n", val, counter); pthread_mutex_unlock(&mutex); pthread_cond_signal(&full); // 发送缓冲区满信号 sleep(1); } return NULL; } void *consumer(void *arg) { int val; while (1) { pthread_mutex_lock(&mutex); while (counter == 0) // 缓冲区空,等待生产者 pthread_cond_wait(&full, &mutex); val = buffer[--counter]; // 从缓冲区取出 printf("消费者:%d,缓冲区大小:%d\n", val, counter); pthread_mutex_unlock(&mutex); pthread_cond_signal(&empty); // 发送缓冲区空信号 sleep(1); } return NULL; } int main(int argc, char *argv[]) { pthread_t tid1, tid2; srand(time(NULL)); pthread_create(&tid1, NULL, producer, NULL); pthread_create(&tid2, NULL, consumer, NULL); pthread_join(tid1, NULL); pthread_join(tid2, NULL); return 0; } ``` 在上面的代码中,使用了互斥锁和条件变量来实现线程同步。生产者线程和消费者线程分别使用互斥锁来保护共享变量(缓冲区计数器和缓冲区数组),并使用条件变量来等待对方的信号。当生产者向缓冲区放入数据时,如果缓冲区已满,则会等待消费者取走数据后再放入;当消费者从缓冲区取出数据时,如果缓冲区已空,则会等待生产者放入数据后再取出。这样就保证了生产者和消费者之间的同步和互斥。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值