目录
多生产者-多消费者问题
可不可以不使用互斥信号量?
当缓冲区的大小为2呢?
结论
多生产者-多消费者问题
多个不同类别的消费者和生产者,他们生产的和要消费的产品使不一样的
1、分析关系:找出题目中描述的各个进程,分析它们之间的同步、互斥关系
互斥关系:对缓冲区(盘子)的访问要互斥地进行
同步关系:
- 父亲将苹果放入盘子后(前操作),女儿才能取苹果(后操作)
- 母亲将橘子放入盘子后(前操作),儿子才能取橘子(后操作)
- 只有盘子为空时(孩子们的前操作),父亲或母亲才能放入水果(父母们的后操作)
- ”盘子为空“事件可由儿子或女儿触发,事件发生后才允许父亲或母亲放水果
2、整理思路: 根据各进程地操作流程确定P、V操作的大致顺序
3、设置信号量:设置需要的信号量,并根据题目要求确定信号量初值(互斥信号量一般为1,同步信号量的初始值要看对应资源的初始值为多少)
1、plate信号量:开始时父母进程就可以向盘子中放一个水果,所以plate的初始值可以为1
2、apple与orange信号量:开始时孩子们并未获得父母们给的水果,所以信号量初始值为0
semaphore mutex = 1; //实现互斥访问盘子(缓冲区) semaphore apple = 0; //盘子中有几个苹果 semaphore orange = 0; //盘子中有几个橘子 semaphore plate = 1; //盘子中还可以放多少个水果
4、代码实现
可不可以不使用互斥信号量?
semaphore apple = 0; //盘子中有几个苹果 semaphore orange = 0; //盘子中有几个橘子 semaphore plate = 1; //盘子中还可以放多少个水果
1、刚开始,儿子、女儿进程即使上处理机运行也会被阻塞
2、刚开始,如果是父进程先上处理机运行,则:
- 父亲准备完苹果后,P操作后plate--变为0,可以访问盘子,然后切换至母亲
- 母亲准备完橘子后,P操作后plate--变为-1,需要阻塞循环等待,然后切换至父亲
- 父亲将苹果放入盘子后,V操作后apple++变为1,女儿进程被唤醒,并且其它进程即使运行也会被阻塞
- 女儿进程被唤醒后,P操作后apple--变为0,可以访问盘子,然后执行V操作plate++变为0,然后母亲进程被唤醒(父进程已经完全结束)
- 母进程被唤醒后,不会再执行P操作,可以直接去访问盘子,然后执行V操作orange++变为1,然后儿子进程被唤醒(母进程已经完全结束)
- 儿子进程被唤醒后,P操作orange--变为0,可以访问盘子,然后执行V操作plate++变为1(重新变为初始值)
当缓冲区的大小为2呢?
semaphore apple = 0; //盘子中有几个苹果 semaphore orange = 0; //盘子中有几个橘子 semaphore plate = 2; //盘子中还可以放多少个水果
1、刚开始,儿子、女儿进程即使上处理机运行也会被阻塞
2、刚开始,如果是父进程先上处理机运行,则:
- 父亲准备完苹果后,P操作后plate--变为1,可以访问盘子,然后切换至母亲
- 母亲准备完橘子后,P操作后plate--变为0,可以访问盘子,然后切换至父亲
- 父亲向盘子中放苹果后,切换至母亲
- 母亲向盘子中放橘子后,可能覆盖原来父亲进程放入的苹果(数据覆盖)
结论
1、进程由阻塞被唤醒后,不再执行原来导致阻塞的代码段,而是直接执行后序的代码段
2、当缓冲区大小等于1,有可能(不绝对)即使不设置专门的互斥变量mutex,也不会出现多个进程同时访问盘子的现象:本题中的缓冲区大小为1,再任何时刻,apple、orange、plate三个同步信号量中最多只有一个是1,因此在任何时刻,最多只有一个进程的P操作不会被阻塞,并顺利地进入临界区
3、当缓冲区大小1时,必须设置专门的互斥变量mutex,保证不会出现数据覆盖的问题
4、解决”多生产者-多消费者问题“的关键在于理清复杂的同步关系,在分析同步问题(一前一后问题)的时候不能从单个进程行为的角度来分析,要把”一前一后“发生的事看作是两种”事件“的前后关系,如果从单个进程行为的角度来考虑的话,我们会有以下结论:
~over~