我不了解生产者 - 消费者问题的经典算法(来自维基百科:)
semaphore mutex = 1 semaphore fillCount = 0 semaphore emptyCount = BUFFER_SIZE procedure producer() { while (true) { item = produceItem() down(emptyCount) down(mutex) putItemIntoBuffer(item) up(mutex) up(fillCount) } up(fillCount) //the consumer may not finish before the producer. } procedure consumer() { while (true) { down(fillCount) down(mutex) item = removeItemFromBuffer() up(mutex) up(emptyCount) consumeItem(item) } }
我注意到生产者和消费者都在弄乱缓冲区之前锁定了“互斥锁”,然后将其解锁。如果是这种情况,即在任何给定时刻只有一个线程正在访问缓冲区,我真的不明白上述算法与简单解决方案的区别仅在于只需要在缓冲区上设置保护互斥:
semaphore mutex = 1 procedure producer() { while (true) { item = produceItem() flag = true while (flag) { down(mutex) if (bufferNotFull()) { putItemIntoBuffer(item) flag = false } up(mutex) } } } procedure consumer() { while (true) { flag = true while (flag) { down(mutex) if (bufferNotEmpty()) { item = removeItemFromBuffer() flag = false } up(mutex) } consumeItem(item) } }
我只能想到必须使用'fillCount'和'emptyCount'信号量是调度。
也许第一个算法是确保在5个消费者等待空缓冲区(零'fillCount')的状态下,确保当新的生产者出现时,它将超过其“向下”( emptyCount)“快速声明并迅速获得'互斥'。
(而在另一种解决方案中,消费者将不必要地将'互斥体'放弃,直到新生产者获得它并插入一个项目)。
我是对的吗?我错过了什么吗?
答案 0 :(得分:3)
如果缓冲区中没有消息,则消费者将关闭互斥锁,检查缓冲区,发现它是空的,在互斥锁上,循环回来并立即重复该过程。简单来说,消费者和生产者陷入繁忙的循环中,这会占据CPU核心的100%。这也不仅仅是一个理论问题。您可能会发现每次运行程序时计算机的风扇都会开始旋转。
答案 1 :(得分:2)
生产者/消费者模式的漏洞概念是只有在满足某些条件时才能访问共享资源(缓冲区)。并且不要使用不必要的CPU周期以确保它们得到满足。
消费者:
制片:
非常重要的是要注意:
答案 2 :(得分:1)
不仅仅是锁定缓冲区。
第一个程序中的fillCount
信号量是在没有任何东西可以消耗时暂停消费者。没有它,你会不断地查询缓冲区以查看是否有任何东西可以获取,这非常浪费。
同样,当缓冲区已满时,emptyCount
信号量会暂停生产者。
答案 3 :(得分:0)
如果涉及多个消费者,则存在饥饿问题。在后一示例中,消费者检查循环中的项目。但是,当他再次尝试时,其他一些消费者可能会“窃取”他的物品。再次,又一次。那不太好。