先给出问题背景:桌子上有一个盘子,每次只能向其中放入一个水果,爸爸专向盘子里放苹果,妈妈专向盘子里放橘子,儿子专等着吃盘子里的橘子,女儿专等着吃盘子里的苹果。只有字盘子是空的时候,爸爸或妈妈才能向盘子里放水果;只有在盘子里有自己想要的水果时,儿子或女儿才能取出盘子里的水果吃掉。
分析:
对盘子的访问要互斥
同步关系(一前一后)
1 父亲将苹果放进盘子后,女儿才能取走苹果
2 母亲将橘子放进盘子后,儿子才能取走橘子
3 盘子为空时,爸爸或妈妈才能往盘子里放水果(盘子为空这个事件可以由女儿或儿子触发)
根据上面的分析,我们可以得出下面的几个信号量
1 | semaphore mutex = 1; //互斥信号量 |
具体代码实现
1 | semaphore mutex = 1; |
注意这里还是互斥的P操作要写在同步的P操作之后,避免产生死锁问题
现在来考虑考虑,我可不可以不要互斥信号量?
一开始盘子为空,女儿和儿子想运行都会被阻塞,如果父亲先操作,那么会让plate变成0,这个时候母亲要是想放橙子会被阻塞;女儿当然可以拿苹果,其他进程都会被阻塞,如此分析看来,我不要互斥信号量是完全ok的
1 | semaphore apple = 0; |
那如果我的盘子可以放两个水果呢?plate的初始值就是2,当父亲放进苹果后,plate变为1,母亲也想放橙子,发现也可以,于是就出现了父亲母亲同时访问缓冲区的情况,因而,如果缓冲区容量为1,我们可以不设互斥信号量,但如果缓冲区容量大于1,就必须设置信号量
那为了避免出麻烦,我们就不管三七二十一都给他设上互斥信号量,肯定是没有问题的。
最后想说一个思想,在多消费者多生产者的问题中,不同于之前的生产者消费者问题,我们不应该把每个进程看成一个整体来考虑问题,应该将事件拿出来分析问题
就上面的问题来讲,如果我不按时间角度来分析,那就是只有儿子将橘子取走了,母亲才能向盘子里放橘子;只有女儿将苹果取走了,爸爸才能把苹果放在盘子里;那仔细想想,我一定要有这个先后顺序吗,比如说女儿取走苹果之后,既可以是母亲方橘子,也可以是父亲放苹果,因此应该想象成事件间的前后关系,就是只有盘子空了,父亲或母亲才能放水果。
再者,通过栗子,我们应该明白,所谓多消费者多生产者应该不是数量上的多,而应该是种类上的多。