Многопоточность: классический продюсер потребительский алгоритм
-
27-09-2019 - |
Вопрос
Что-то, чего я не понимаю о классическом алгоритме для продюсер-потребительской проблемы (от Wikipedia :)
SEMAPHORE MUTEX = 1 SEMAPHORE FLAILCOUNT = 0 SEMAPHORE joycount = Buffer_Size Procenter Production () {While While (true) {item = productionem () down (joincount) down (mutex) putitemintobuffer (элемент) вверх (mutex) up (fillcount) up ( Fillcount) // Потребитель может не закончить перед производителем. } Процедура Потребитель () {while (true) {down (fillcount) down (mutex) item = ustheriTemfrombiffer () up (mutex) (jugcountcount) consumeitem (item)}}
Отмечу, что как продюсеры, так и потребители блокируют «MUTEX» перед возобновлением буфера, и разблокировать его после этого. Если это так, то есть только один поток обращается к буферу в любой момент, я на самом деле не вижу, как вышеупомянутое алго отличается от простого решения, которое влечет за собой только охрану Mutex на буфер:
SEMAPHORE MUTEX = 1 Производитель процедуры () {Whaue (true) {item = productiTem () flag = true while (flag) {down (mutex), если (flagernotfulll ()) {putitemintobuffer (item) flag = fals = false} (mutex) }}} Процедура Потребитель () {While (True) {flag = true while withy (flag) {down (mutex), если (buffernoTempty ()) {item = flageletimfrombuffer () flag = false} (Mutex)} ConsumeItem (item) }}
Только что я могу думать о том, что требует, используя семафоры «FillCount» и «jogryCount» планирование.
Может быть, первое вол в том, чтобы убедиться, что в состоянии, где 5 потребителей ждут на пустом буфере (нулевой «Fillcount»), уверены, что когда приходит новый продюсер, он пройдет мимо его «вниз (jointCount)» Выражение быстро и быстро получите «Mutex».
(В то время как в другом решении потребители не понравятся, получают только «Mutex» только для того, чтобы отказаться от него, пока новый производитель не получит его и вставит элемент).
Я прав? Я что-то упускаю?
Решение
Если в буфере нет сообщений, потребитель снинется на мьютекс, проверяет буфер, обнаружил, что он пуст, вверх по мьютексу, цикл обратно и немедленно повторите процесс. По простым условиям, потребители и производители застряли в оживленных петель, которые разворачивают 100% CPU Core. Это не просто теоретическая проблема. Вы вбередитесь, что вентилятор вашего компьютера начинает вращаться каждый раз, когда вы запускаете свою программу.
Другие советы
Концепция отверстий производителя / потребительской узор состоит в том, что Общий ресурс (буфер) доступен только в том случае, если определенные критерии будут выполнены. Отказ И не использовать ненужные циклы ЦП, чтобы убедиться, что они встречаются.
Потребитель:
- Подождите, если нечего потреблять (=> пустой буфер).
Режиссер:
- Подождите, если в буфере недостаточно места.
И для обоих очень важно отметить:
- Ждать! = Спин ждать
Есть больше, чем просто фиксировка буфера.
То fillCount
Семафор в первой программе - приостановить потребителя (ы), когда ничего не осталось потреблять. Без этого вы постоянно выбираете буфер, чтобы увидеть, есть ли что-нибудь, чтобы получить, и это довольно расточительно.
Аналогично, то emptyCount
Семафор приостанавливает производителю, когда буфер заполнен.
Существует голодная проблема, если участвует более одного потребителя. В последнем примере потребительские проверки для элемента в петле. Но к тому времени, когда он собирается попробовать еще раз, какой другой потребитель может «украсть» его предмет. И в следующий раз снова и снова. Это не приятно.