Linux:生产者消费者模型下篇(基于环形队列)

本文介绍了如何使用环形队列实现生产者消费者模型。通过模运算实现数组的环形操作,并通过判断条件解决队列的空满问题。文章详细阐述了四个关键规则,并利用信号量进行同步和互斥,确保生产者和消费者的正确交互。最后,给出了代码实现及运行结果的描述。

基于环形队列的生产者消费者模型

上篇讲解了生产者消费者模型以及基于BlockingQueue实现该模型,下篇这里就实现一个基于环形队列的生产者消费者模型吧!这个环形队列用数组来实现。

1.如何把数组设置一个环形的队列呢?
利用模运算来实现顺序结构的环形操作。0 ~ 9模10依然是0 ~ 9,10模10就变成0了,也就回到了数组的头部,从而实现一个环形队列。

2.那么如何判断该环形队列的空和满呢?
刚开始的时候生产者和消费者指向同一块空间,生产者在生产的时候,先判断前面的格子里是不是消费者,如果前面的格子里不是消费者就在当前格子里生产数据,然后++,如果前面的格子里是消费者,那就不在当前的格子里生产数据,保持不动。
假如现在有10个格子,下标为0 ~ 9,消费者依然在0号格子,生产者生产到8号格子了,那么生产者判断9号格子不是消费者,于是在8号格子里生产数据,然后++到9号格子,此时继续判断,生产者发现9号格子的下一个0号格子里是消费者,所以此时生产者不再生产,表示该环形队列已经满了。所以我们采用浪费一个格子的操作实现了判空和判满。

3.四条规则

  1. 消费者不能超过生产者(如果消费者快,但是生产者还没生产完的时候,消费者就不能进行消费,消费者必须等生产者生产完)
  2. 生产者不能把消费者套一个圈(如果生产者快,而且队列已经被生产者生产满了,此时生产者就不能进行生产了,生产者此时就必须等消费者消费完才能继续生产)
  3. 环形队列为空的时候,生产者先出发
  4. 环形队列为满的时候,消费者先出发

4.怎么实现?
引入两个信号量,一个记录格子资源个数,另一个记录数据资源个数。
生产者生产的时候要申请空格子(P格子:格子资源数减一),那么生产完毕之后有数据的格子就会多一个(V数据:数据资源数加一)。
消费者消费的时候就是要拿取有数据的格子(P数据:数据资源数减一),那么消费完毕之后空格子就会多一个(V格子:格子资源数加一)

具体实现代码解释:
在这里插入图片描述
运行结果:
此时生产者生产的快,因此会迅速把环形队列生产满,满了之后基于信号量的同步和互斥它就不能生产了,因此消费者开始每隔一秒消费一条数据,当消费者消费完一条数据之后,格子信号量就会增加1,因此生产者又会快马加鞭的生产一条数据,消费者再隔一秒消费一条数据,生产者还是穷追不舍的又生产一条数据,因此看到的结果是生产者迅速生产满之后,就变成了消费一条生产一条。
在这里插入图片描述
代码如下:

  1 #include <iostream>
  2 #include <pthread.h>
  3 #include <stdlib.h>
  4 #include <time.h>
  5 #include <semaphore.h>
  6 #include <unistd.h>
  7 #define NUM 16
  8 class ring{
  9     private:
 10         int Ring[NUM];
 11         sem_t blank_sem;
 12         sem_t data_sem;
 13         int p_step;
 14         int c_step;
 15     public:
 16         void P(sem_t *sem)
 17         {
 18             sem_wait(sem);
 19         }
 20         void V(sem_t *sem)
 21         {
 22             sem_post(sem);
 23         }
 24     public:
 25         ring()
 26             :p_step(0),c_step(0)
 27         {
 28             sem_init(&blank_sem,0,NUM);
 29             sem_init(&data_sem,0,0);
 30         }
 31         void PushData(const int &data)
 32         {
 33             P(&blank_sem);
 34             Ring[p_step]=data;
 35             p_step++;
 36             p_step%=NUM;
 37             V(&data_sem);
 38         }
 39         void PopData(int &data)
 40         {
 41             P(&data_sem);
 42             data=Ring[c_step];
 43             c_step++;
 44             c_step%=NUM;
 45             V(&blank_sem);
 46         }
 47         ~ring()
 48         {
 49             sem_destroy(&blank_sem);
 50             sem_destroy(&data_sem);
 51         }
 52 };
 53 void *product(void *arg)
 54 {
 55     ring *r=(ring *)arg;
 56     srand((unsigned long)time(NULL));
 57     while(1)
 58     {
 59         int data=rand()%100+1;
 60         r->PushData(data);
 61         std::cout<<"product done:"<<data<<std::endl;
 62     }
 63 }
 64 void *consume(void *arg)
 65 {
 66     ring *r=(ring *)arg;
 67     while(1)
 68     {
 69         int data;
 70         r->PopData(data);
 71         std::cout<<"consume done:"<<data<<std::endl;
 72         sleep(1);
 73     }
 74 }
 75 int main()
 76 {
 77     ring r;
 78     pthread_t p,c;
 79     pthread_create(&p,NULL,product,(void *)&r);
 80     pthread_create(&c,NULL,consume,(void *)&r);
 81     pthread_join(p,NULL);
 82     pthread_join(c,NULL);
 83     return 0;
 84 }
多角色体系支持管理员、教师、学生三种角色,权限分级管控:管理员:负责系统配置、用户管理、数据维护、权限分配等全局操作。教师:创建题库、组卷、发布考试、手动阅卷、查看成绩统计。学生:查看考试列表、参与在线考试、查看个人成绩与错题解析。实现用户注册(支持批量导入学生信息)、登录(账号密码 / 验证码登录)、个人信息管理(密码修改、头像设置)。班级与课程关联教师可创建班级并添加学生,将考试与特定班级 / 课程绑定,确保学生仅能参与授权范围内的考试。二、题库管理功能题库创建与维护支持多种题型录入:单选题、多选题、判断题、填空题、简答题、编程题(支持 Python 代码在线运行)等。题目信息包括:题干(支持图文混排)、选项(选择题)、答案、解析、难度等级(易 / 中 / 难)、知识点标签(如 “Python 函数”“高数积分”)、分值。支持题目批量导入(Excel/Word 模板)、导出、批量修改(如统一调整难度),自动检测重复题目。题库分类与检索按课程、章节、知识点对题目分类,形成结构化题库(如 “计算机基础→操作系统→进程管理”)。支持多条件检索:按题型、难度、关键词搜索题目,便于教师快速组卷。三、试卷管理与考试发布智能组卷功能手动组卷:教师从题库中手动选择题目,自定义每题分值,系统自动计算总分。随机组卷:设置组卷规则(如 “10 道单选 + 5 道多选 + 3 道简答,总分 100 分,难度比例 2:6:2”),系统从题库中随机抽取符合条件的题目,支持生成多套平行试卷。试卷预览与调整:组卷后可预览完整试卷,修改题目或分值,确认无误后保存为试卷模板。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值