Каково значение condition.notify() в поточном модуле python?
Поэтому я использую условие Python из модуля потоков:
from threading import Thread, Condition
condition = Condition()
У меня есть класс Producer (подкласс Thread), который, по существу, в цикле for добавляет элементы в очередь до тех пор, пока очередь не заполнится (т. Е. Не достигла определенной максимальной длины), и класс Consumer, который в цикле for выводит элементы, если очередь не пуста., В источнике, если очередь заполнена, у нас есть оператор condition.wait (), и аналогично в классе-потребителе, если очередь пуста, у нас есть условие condition.wait (). Если ни одно из этих условий не выполнено (очередь не заполнена и не пуста), каждый класс делает свое дело (добавляет элемент в очередь или извлекает элемент соответственно для Producer или Consumer), а затем перед освобождением условия (condition.release ()), у нас есть условие condition.notify (). Я прочитал из документации, что notify () пробуждает один из ожидающих потоков.
Мой вопрос сейчас в два раза:
- Что именно "просыпаться" означает для потока?
- Когда я удалил операторы notify () из обоих классов, моя программа работает нормально, за несколько итераций циклов for (т. Е. Производитель выталкивает элементы, а потребитель выталкивает элементы), а затем в какой-то момент производитель продолжает помещать элементы в очередь без потребителя работает, очередь заполняется, но потребитель никогда не запускается снова, и программа просто останавливается. Какое значение имеет метод notify (), который важен для работы этой программы.
Большое спасибо за вашу помощь:)
1 ответ
1) Он сигнализирует потоку, ожидающему снятия блокировки, он может продолжить выполнение.
2) Condition.notify(n)
занимает до n
потоки из внутренней очереди и звонки release
на замках они ждут - тем самым разбудив их. Если внутренняя очередь пуста, проснуться некому, и notify
звонок не имеет никакого эффекта. Вот почему с самого начала, удаление notify
не имел никакого эффекта, но когда-то потребительские темы назывались wait
Не было никого, кто бы разбудил их, и они ждали вечно.
TL;DR
Пробуждение здесь можно рассматривать как пробуждение производителя или потребителя от сна И информирование их о том, что они могут вернуться к работе, как только их общий PPE (базовая блокировка) станет доступен.
Потребитель увидел, когда очередь пуста, и пошел спать, ожидая, пока производитель разбудит его, когда он добавит в очередь.
Но вы лишили производителя возможности разбудить потребителя.
Продюсер увидел, когда очередь наполнилась, и пошел спать, ожидая, пока потребитель разбудит его, когда он берет из очереди.
Но вы лишили потребителя возможности разбудить производителя.
И теперь они оба спят.
Правильное обсуждение
Ключ к пониманию значения Condition.notify()
заключается в осознании того, что когда ты wait()
Используя условие, вы НЕ ждете, когда станет доступной его базовая блокировка, а, скорее, вы ждете какого-либо уведомления или тайм-аута для этого условия.
Согласно документам Python о threading.Condition.wait
wait(timeout=None) Wait until notified or until a timeout occurs...
Когда вы вызываете notify
при условии, вы по сути информируете n потоков, которые вызвали wait
на этом объекте условия, что они могут перестать ждать, как только они смогут получить базовую блокировку.
Это можно сделать из документации Python по threading.Condition.notify
notify(n=1) ... Note: an awakened thread does not actually return from its wait() call until it can reacquire the lock. Since notify() does not release the lock, its caller should.
А теперь вот мое обоснованное предположение о том, что происходит с вашим кодом:
- Производитель помещает ряд элементов в очередь.
- Потребитель потребляет некоторое количество товаров из очереди.
- Очередь скоро пустеет.
- Потребитель
wait()
s, чтобы получить уведомление о том, что он может возобновить потребление (как только сможет получить базовую блокировку) - Производитель помещает элементы в очередь.
- Продюсер никогда не добирается до
notify()
потребителю, что он может возобновить потребление. - Очередь скоро заполнится.
- Режиссер
wait()
s, чтобы получить уведомление о том, что он может возобновить производство (как только сможет получить базовую блокировку) - Потребитель ждет, чтобы его разбудил Продюсер, а Продюсер ждет, чтобы его разбудил Потребитель.
- Безвыходное положение!