Что-то, чего я не понимаю в классическом алгоритме для задачи Продюсер-Потребитель (из Википедии:)
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)
}
}
Я отмечаю, что как производители, так и потребители блокируют 'mutex' перед тем, как связываться с буфером, а затем разблокируют его. Если это так, то есть только один поток обращается к буферу в любой момент, я действительно не вижу, как вышеприведенный алгоритм отличается от простого решения, которое влечет за собой только размещение защитного мьютекса над буфером:
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) "быстро и быстро получить 'mutex'.
(тогда как в другом решении потребители будут без необходимости получать «мьютекс» только для того, чтобы отказаться от него, пока новый производитель не получит его и не вставит элемент).
Я прав? Я что-то упустил?