所谓生产者-消费者问题实际上就是有一个缓冲区,生产者生产好了放进去,消费者可以从缓冲区中取出来产品用,但是需要注意的是肯定是要保证各进程都是互斥的,生产者和消费者要互斥不用多说,假设现在有两个生产者想要把产品放进缓冲区,如果都想放在同一个地方怎么办,因此一定要保证互斥性,那互斥的初始信号量是1,因此我们要设置一个互斥信号量 semaphore mutex = 1;
假设初始的缓冲区是大小为n的空缓冲区;
首先当缓冲区满了,就不能让生产者在把产品放进去了,得等消费者取出产品释放空间了才行,也就是说在缓冲区满这种情况,必须是消费者在生产者之前,那这就是要有一个同步,同步信号量就是空闲缓冲区的大小,就是要确认一下空闲缓冲区有没有位置,空闲缓冲区的初始值就是n ,semaphore empty = n;
当缓冲区是空的时候,同样不能让消费者从中取出产品,那这里就是生产者要在消费者之前执行,那这里也是一个同步关系,这里的同步信号量就是产品数量,初始值为0,semaphore full = 0;
;
直观点看就是下面这张图
下面上代码
1 | semaphore mutex = 1; |
需要仔细理解一下full和empty,注意full缓冲区里的产品数,empty是缓冲区空闲的大小,而且敲重点同步信号量定的是初始值!!!不要想当然。还有就是要注意实现互斥的P操作一定要写在实现同步的P操作之后,V操作无所谓先后,为什么呢?如果颠倒了位置(2143),假设缓冲区已经满了,即empty为0,full为n,如果先执行互斥的P操作,mutex为0,再执行P(empty),因为已经没有空闲缓存区了,因此生产者被阻塞,切回消费者,因为mutex已经为0了,消费者这边P(mutex)也走不下去了,消费者也则色,这就造成了消费者等生产者释放临界区,生产者等待消费者释放空闲缓冲区,生产者和消费者循环等待被对方唤醒,形成死锁,同样的若缓冲区为空,也会造成死锁.
还有就是尽量不要把”生产一个产品”和”使用产品”放在缓冲区那步代码,最好像上面那么些,不然占用资源会造成忙等。