多生产者-多消费者问题(有例题!!!)

前言

此篇文章是我在B站学习时所做的笔记,大部分图片都是课件老师的PPT,方便复习用。此篇文章仅供学习参考。


提示:以下是本篇文章正文内容

问题描述

桌子上有一只盘子,每次只能向其中放入一个水果。爸爸专向盘子中放苹果,妈妈专向盘子中放橘子,儿子专等着吃盘子中的橘子,女儿专等着吃盘子中的苹果。只有盘子空时,爸爸或妈妈才可向盘子中放一个水果。仅当盘子中有自己需要的水果时,儿子或女儿可以从盘子中取出水果。用PV操作实现上述过程。
在这里插入图片描述
解说:
咱们上个小节学过的生产者消费者模型,我们可以把这个盘子看作是一个大小为1,初始为空的缓冲区,然后把父亲和母亲看作是两个生产者进程,把女儿和儿子分别看做是两个消费者进程,当然与上一节所讲的生产者,消费者模型不同的是,这个小节中的这些生产者和这些消费者,他们所生产的东西和他们所消费的东西类型是不一样的,而上个小节我们介绍的例子当中,所有的生产者生产的都是一种东西,而所有的消费者也都是消费同一种东西,所以这就是为什么把这个小节的这个问题称作多生产者,多消费者的原因,所谓的多不是指多个应该把它理解为是多类不同类别的生产者和不同类别的消费者,他们所需要生产的和所需要消费的这些产品是不一样的,那么这个问题我们怎么用pv操作来解决呢?

问题分析

在这里插入图片描述

如何实现

如果盘子容量为1的话

在这里插入图片描述
解说:
我们总共实名了四个信号量一个,其中一个是互斥信号量,另外三个是同步信号量,父亲进程和母亲进程做的事情,就是不断地准备一个自己的水果,然后再把自己的水果放到盘子里,而女儿进程和儿子进程做的事情,就是不断地从盘子中取出自己喜欢的水果,并且把这个水果给吃掉,那父亲进程再放入水果之前,需要先检查这个盘子是否为空,所以在苹果放入盘子之前,父亲进程需要对这个信号量进行一个P操作来检查,此时盘子中到底还可以放多少个水果。那如果这个苹果已经放入盘子之后,父亲进程又需要对apple这个同步信号量执行一个V操作,用来让apple的值加一来告诉女儿进程此时苹果盘子中的苹果数量已经加一了,而母亲进程也一样,它在把橘子放入盘子之前,需要同样需要对盘子中还可以放多少个水果进行检查。如果说此时这个盘子中已经有别的水果,那么母亲进程会被阻塞,在这个地方(P(plate);)会被阻塞,而当母亲进程把橘子放入盘子之后,它也同样也需要对orange这个同步信号量执行一个操作来通知儿子进程,此时盘子当中的橘子数量已经加一了,那么女儿进程和儿子进程在取出自己喜欢的水果之前分别需要检查此时这个盘子当中是否已经有自己喜欢的水果,所以女儿进程需要对apple这个信号量执行P操作,而儿子进程是对orange这个信号量执行P操作。而女儿进程在从盘子中取出苹果之前,需要先检查此时盘子中苹果的数量是否足够,如果没有苹果的话,它将被阻塞,而当他把苹果取出之后,又需要对plate这个信号量执行V操作,用来告诉父亲进程和母亲进程,此时盘子已经变空了,那么儿子进程以和女儿进程也类似,只不过是它在检查的时候,是检查盘子当中是否有橘子。那这样的话,我们就实现了咱们在这个图中表示的这些同步关系,另外我们还需要实现各个进程对盘子这种缓冲区的互斥访问,所以我们在这些进程访问盘子之前,对这个互斥信号量执行一个P操作,访问之后又执行一个V操作,分别是对这个临界区进行加锁和解锁,其他的这些进程也一样。

问题:可以不可以不用互斥信号量?

在这里插入图片描述
分析:刚开始,儿子、女儿进程即使上处理机运行也会被阻塞。如果刚开始是父亲进程先上处理机运行,则:父亲P(plate),可以访问盘子→母亲P(plate),阻塞等待盘子→父亲放入苹果V(apple),女儿进程被唤醒,其他进程即使运行也都会阻塞,暂时不可能访问临界资源(盘子)→女儿P(apple),访问盘子,V(plate),等待盘子的母亲进程被唤醒→母亲进程访问盘子(其他进程暂时都无法进入临界区)→…

原因在于:本题中的缓冲区大小为1,在任何时刻, apple、orange、plate三个同步信号量中最多只有一个是1。因此在任何时刻,最多只有一个进程的P操作不会被阻塞,并
顺利地进入临界区…

如果盘子容量为2的话

在这里插入图片描述
分析:父亲P(plate),可以访问盘子→母亲P(plate),可以访问盘子→父亲在往盘子里放苹果,同时母亲也可以往盘子里放橘子。于是就出现了两个进程同时访问缓冲区的情况,有可能导致两个进程写入缓冲区的数据相互覆盖的情况。

  • 如果缓冲区大小大于1,就必须专门设置一个互斥信号量mutex来保证互斥访问缓冲区。
  • 如果缓冲区大小为1,那么有可能不需要设置互斥信号量就可以实现互斥访问缓冲区的功能。

知识回顾与重要考点

  • 总结:在生产者-消费者问题中,如果缓冲区大小为1,那么有可能不需要设置互斥信号量就可以实现互斥访问缓冲区的功能。当然,这不是绝对的,要具体问题具体分析。
  • 建议:在考试中如果来不及仔细分析,可以加上互斥信号量,保证各进程一定会互斥地访问缓冲区。但需要注意的是,实现互斥的P操作一定要在实现同步的P操作之后,否则可能引起“死锁”。

PV操作题目的解题思路:

  1. 关系分析。找出题目中描述的各个进程,分析它们之间的同步、互斥关系。
  2. 整理思路。根据各进程的操作流程确定P、V操作的大致顺序。
  3. 设置信号量。设置需要的信号量,并根据题目条件确定信号量初值。(互斥信号量初值一般为1,同步信号量的初始值要看对应资源的初始值是多少)

解决“多生产者-多消费者问题”的关键在于理清复杂的同步关系

  • 在分析同步问题(一前一后问题)的时候不能从单个进程行为的角度来分析,要把“一前一后”发生的事看做是两种“事件”的前后关系。
  • 比如,如果从单个进程行为的角度来考虑的话,我们会有以下结论:
    如果盘子里装有苹果,那么一定要女儿取走苹果后父亲或母亲才能再放入水果
    如果盘子里装有橘子,那么一定要儿子取走橘子后父亲或母亲才能再放入水果
  • 这么看是否就意味着要设置四个同步信号量分别实现这四个“一前一后”的关系了?
    正确的分析方法应该从“事件”的角度来考虑,我们可以把上述四对“进程行为的前后关系”抽象为一对“事件的前后关系”
  • 盘子变空事件→放入水果事件。“盘子变空事件”既可由儿子引发,也可由女儿引发;“放水果事件”既可能是父亲执行,也可能是母亲执行。这样的话,就可以用一个同步信号量解决问题了
    在这里插入图片描述
  • 9
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
m个生产者和n个消费者问题是一个常见的多线程同步问题,其中生产者线程负责生产数据并将其放入共享缓冲区中,而消费者线程负责从共享缓冲区中取出数据并进行处理。这个问题的关键在于如何保证生产者消费者之间的同步,以防止数据竞争和死锁。 一种解决方案是使用信号量来实现同步。我们可以使用两个信号量来实现这个问题:一个是空槽信号量,表示缓冲区中空余的槽数量,初始值为缓冲区大小;另一个是满槽信号量,表示缓冲区中已经有数据的槽数量,初始值为0。生产者消费者线程都需要在访问共享缓冲区之前获取信号量,操作完成后再释放信号量。 下面是一个伪代码示例: ``` // 定义信号量 Semaphore emptySlots = new Semaphore(bufferSize); Semaphore fullSlots = new Semaphore(0); // 定义共享缓冲区 Buffer buffer = new Buffer(bufferSize); // 定义生产者线程 class ProducerThread extends Thread { public void run() { while (true) { // 生产数据 Data data = produceData(); // 获取信号量 emptySlots.acquire(); // 将数据放入缓冲区 buffer.put(data); // 释放信号量 fullSlots.release(); } } } // 定义消费者线程 class ConsumerThread extends Thread { public void run() { while (true) { // 获取信号量 fullSlots.acquire(); // 从缓冲区取出数据 Data data = buffer.get(); // 处理数据 consumeData(data); // 释放信号量 emptySlots.release(); } } } ``` 在这个示例中,生产者线程会不断地生产数据,并将其放入缓冲区中。如果缓冲区已满,则生产者线程会等待直到有空余的槽位。消费者线程会不断地从缓冲区中取出数据,并进行处理。如果缓冲区为空,则消费者线程会等待直到有数据可用。 使用信号量可以很好地解决m个生产者和n个消费者问题,保证线程之间的同步和互斥

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

蜗牛_Chenpangzi

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

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

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

打赏作者

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

抵扣说明:

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

余额充值