操作系统—生产者消费者

  1. 问题描述及需求分析
    实现生产者和消费者之间的通信,即生产者-消费者问题。生产者一次生成一个元素放入缓冲池中,消费者一次可以从缓冲池中取出一个元素。要求实现生产者与消费者之间的同步,即当缓冲池为空时,消费者不能取出元素,而当缓冲池为满时,生产者不能生产元素。实验的输出要能跟踪生产者的每次“生产”行为,以及消费者的每次“消费”行为。并在每次行为后输出缓冲池的元素个数,从而了解两者之间通信的过程。

  2. 实验设计
    该实验需要注意的几点:
    在缓冲区为空时,消费者不能再进行消费
    在缓冲区为满时,生产者不能再进行生产
    在一个线程进行生产或消费时,其余线程不能再进行生产或消费等操作,即保持线程间的同步,注意条件变量与互斥锁的顺序。

由于前两点原因,因此需要保持线程间的同步,即一个线程消费(或生产)完,其他线程才能进行竞争CPU,获得消费(或生产)的机会。对于这一点,可以使用条件变量进行线程间的同步:生产者线程在product之前,需要wait直至获取自己所需的信号量之后,才会进行product的操作;同样,对于消费者线程,在consume之前需要wait直到没有线程在访问共享区(缓冲区),再进行consume的操作,之后再解锁并唤醒其他可用阻塞线程。
在访问共享区资源时,为避免多个线程同时访问资源造成混乱,需要对共享资源加锁,从而保证某一时刻只有一个线程在访问共享资源。

  1. 实验代码
    #include
    #include <Windows.h>
    #include
    #include <time.h>
    #include
    #include
    class sbuf {
    private:
    int buffer[5]; //缓冲区大小为5
    int rear; //指向数组最后一个元素
    mutex mu; //互斥信号量
    int empty; //记录空位
    int full; //记录占位
    public:
    void init(); //初始化
    void insert(int item); //放入商品
    void remove(); //取出商品
    void display(); //显示缓冲区
    };
    //初始化
    void sbuf::init() {
    rear = -1;
    empty = 5;
    full = 0;
    }

//放入商品
void sbuf::insert(int item) {
while (1) {
while (!empty) {}
empty -= 1; //P(empty)
mu.lock(); //P(mutex)
cout << “生产的数为:” << item << endl;
buffer[++rear] = item; //将商品放入缓冲区
display();
mu.unlock(); //V(mutex)
full += 1; //V(full)
break;
}
}

//取出商品
void sbuf::remove() {
int item;
while (1) {
while (!full) {}
full -= 1; //P(full)
mu.lock(); //P(mutex)
item=buffer[rear–]; //从缓冲区取出商品
cout << “消费的数为:” << item << endl;
display();
mu.unlock(); //V(mutex)
empty += 1; //V(empty)
break;
}
}
//显示缓冲区
void sbuf::display() {
cout << “缓冲区:”;
if (rear == -1)
cout << “空” << endl;
else {
for (int i = 0; i <= rear; i++)
cout << buffer[i]<<" ";
cout << endl;
}
cout << endl;
}
//生产者线程
void producer(sbuf* p) {
int item;
uniform_int_distribution k(500, 1500);
static uniform_int_distribution u(1, 100);
static default_random_engine e(time(0)); //随机数引擎
for (int i = 0; i < 20; i++) { //生产20次
item = u(e);
p->insert(item);
Sleep(k(e));
}
}
//消费者线程
void consumer(sbuf* p) {
uniform_int_distribution k(1000, 2000);
default_random_engine v(time(0)); //随机数引擎
for (int i = 0; i < 20; i++) { //消费20次
p->remove();
Sleep(k(v));
}
}
int main() {
sbuf p;
p.init();
thread pro(producer, &p); //创建生产者子线程
thread con(consumer, &p); //创建消费者子线程
pro.join(); //阻塞主线程
con.join(); //阻塞主线程
cout << “结束!” << endl;
return 0;
}

  1. 实验结果与分析
    实验结果截图
    向缓冲区加入随机数为生产的商品,消费者可以从缓冲区顶部的数字进行消费,如果缓冲区中没有数字则显示缓冲区为‘空’。

  2. 实验心得
    通过本次实验,我对生产者-消费者问题的相关知识有了更加深刻的理解,进一步掌握了进程的同步的相关概念,理解了利用信号量机制解决进程同步问题的基本方法。队列和链表在C++中是可以直接用已经有的模板的。学会用指针进行遍历。消费者要是能放到缓冲区里就看生产者等待队列里有没有人,有人就唤醒一个生产者。要是缓冲区只有1那么大,最终完成链表中必定是生产者和消费者交替,这是一个验证程序对错的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

engineer_z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值