Многопоточность: классический алгоритм Producer Consumer - PullRequest
2 голосов
/ 30 октября 2010

Что-то, чего я не понимаю в классическом алгоритме для задачи Продюсер-Потребитель (из Википедии:)

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'.

(тогда как в другом решении потребители будут без необходимости получать «мьютекс» только для того, чтобы отказаться от него, пока новый производитель не получит его и не вставит элемент).

Я прав? Я что-то упустил?

Ответы [ 4 ]

3 голосов
/ 30 октября 2010

Если в буфере нет сообщений, потребитель выключит мьютекс, проверит буфер, обнаружит, что он пуст, поднялся на мьютекс, вернется назад и сразу же повторите процесс. Проще говоря, потребители и производители застряли в занятых циклах, которые поглощают 100% ядра процессора. Это не просто теоретическая проблема. Вы можете обнаружить, что вентилятор вашего компьютера начинает вращаться при каждом запуске вашей программы.

2 голосов
/ 30 октября 2010

Концепция дыры в шаблоне производитель / потребитель заключается в том, что общий ресурс (буфер) доступен только при соблюдении определенных критериев .И не использовать ненужные циклы ЦП, чтобы удостовериться, что они выполнены.

Потребитель:

  • Подождите, если нечего потреблять (=> пусто)буфер).

Производитель:

  • Подождите, если в буфере недостаточно места .

Идля обоих очень важно отметить:

  • Подождите! = Ожидание вращения
1 голос
/ 30 октября 2010

Это больше, чем просто блокировка буфера.

Семафор fillCount в первой программе предназначен для приостановки потребителя (ей), когда нечего есть. Без этого вы постоянно опрашиваете буфер, чтобы узнать, есть ли что получить, и это довольно расточительно.

Аналогично, семафор emptyCount приостанавливает продюсера, когда буфер заполнен.

0 голосов
/ 30 октября 2010

Существует проблема голода, если вовлечено более одного потребителя.В последнем примере потребитель проверяет элемент в цикле.Но к тому времени, когда он попробует снова, какой-то другой потребитель может «украсть» его товар.И в следующий раз снова и снова.Это нехорошо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...