потоки Python - как работают "condition.wait" и "condition.notifyAll" - PullRequest
3 голосов
/ 17 сентября 2010

У меня есть следующий «потребительский» код:

    ....

    while 1:

        time.sleep(self.sleeptime)

        cond.acquire() #acquire the lock
        print currentThread(), "lock acquired"

        while itemq.isEmpty():
            cond.wait()

        itemq.consume()
        print currentThread(),"Consumed One Item"
        cond.release()

И следующий код производителя:

....     
while 1 :


           cond.acquire() #acquire the lock
           print currentThread(), "lock acquired"
           print currentThread(),"Produced One Item"
           itemq.produce()
           cond.notifyAll()
           cond.release()

           time.sleep(self.sleeptime)

Я запускаю программу с 1 производителем и 2 потребителями. Я не знаю, какого результата ожидать. Производитель называет «notifyAll ()», поэтому я ожидаю, что оба потребителя проснутся от своего «ожидания». Я вижу, что на самом деле оба покупателя приобретают блокировку, но только тот, кто получил блокировку, фактически получает эту вещь. Может кто-нибудь сказать, пожалуйста, как работает команда "ждать"? Если оба потока получают «notifyAll», как получается, что потребляется только один?

Спасибо, Li

Ответы [ 2 ]

3 голосов
/ 17 сентября 2010

Я думаю документы очень ясны:

Метод wait () снимает блокировку, а затем блокирует, пока не пробудится вызовом notify () или notifyAll () для та же переменная условия в другом нить. После пробуждения он вновь приобретает замок и возвращается. Это также можно указать время ожидания.

и

Примечание: notify () и notifyAll () методы не снимают блокировку; этот означает, что нить или темы пробужденный не вернется из своих Ждать () вызов немедленно, но только когда поток, который вызвал notify () или notifyAll (), наконец, отказывается владение замком. владение замком.

Конечно, только один поток может иметь блокировку в любое время: в этом и заключается цель core , в первую очередь, с блокировкой!

Итак, IOW, notifyAll переводит все ожидающие потоки в состояние готовности к работе, и по сути все ждут, чтобы снова получить блокировку, чтобы они могли продолжить: как только уведомитель снимет блокировку, one из потоков, ожидающих получить эту блокировку, она действительно захватывает ее (другие, если таковые имеются, продолжают ожидать снятия блокировки, разумеется, так что только один поток имеет блокировку в любой момент времени).

0 голосов
/ 17 сентября 2010

Ключ находится в цикле ожидания:

while itemq.isEmpty():
        cond.wait()

cond.wait () реализован примерно так (только для примера):

def wait():
    cond.release()
    wait for notify
    cond.aquire()

Так что только один потребительВыход из функции ожидания одновременно с блокировкой.Первый потребитель, завершивший функцию ожидания, обнаруживает, что itemq.isEmpty () == false, и продолжает потреблять элемент.Затем они снова входят в функцию ожидания и снимают блокировку.

Второй потребитель завершает работу, снова обнаруживает, что itemq.isEmpty () == true, и снова входит в wait ().

...