Логика взаимодействия в Condition - Wait и Notify. Почему не работает, как ожидается?
Отладочный пример выдаёт не то, что ожидаю. Вероятно, не понимаю полностью логику wait и notify. Ниже ожидаемые и получаемые из PуCharm результаты с рядом комментариев + код. Просьба пояснить, что не так. Полезные советы по поумнению тоже принимаются с благодарностью.
Что ожидается от скрипта:
Процесс reader бесконечно печатает сочетание ("хотим это печатать" + 10 раз "и печатаем это"), бесконечно рассылая снятие блокировки процессу writer. Writer регулярно печатает сочетание ("condition" + "и тут дождались").
Что получается (описание):
Процесс writer1 зависает на строке cond.wait(), вероятно, не получив cond.notify от процесса reader. Почему процесс reader не посылает в цикле 10 раз cond.notify - не ясно. Вероятно, застревает на первом же.
PуCharm выдает ряд предупреждений вокруг cond.notify, но я их смысл не могу нагуглить, логика же работы методов Python в synchronize.py, например, пока не понятна. Смысл lock is not owned в данном контексте тоже не ясен.
Что получается (экран):
Process Process-1:
Traceback (most recent call last):
File "C:\Users\Serge\AppData\Local\Programs\Python\Python310\lib\multiprocessing\process.py", line 315, in _bootstrap
self.run()
File "C:\Users\Serge\AppData\Local\Programs\Python\Python310\lib\multiprocessing\process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "C:\Users\Serge\PycharmProjects\pythonProject\main.py", line 10, in reader
cond.notify () #что-то не так
File "C:\Users\Serge\AppData\Local\Programs\Python\Python310\lib\multiprocessing\synchronize.py", line 271, in notify
assert self._lock._semlock._is_mine(), 'lock is not owned'
AssertionError: lock is not owned
хотим это печатать
и печатаем это
зашли сюда
condition
Код:
from multiprocessing import Process, Condition
import time
def reader(cond):
while True:
print('хотим это печатать')
for x in range (10):
print('и печатаем это')
cond.notify () #что-то не так
print('но не печатаем даже это')
time.sleep(1)
def writer1(cond):
print('зашли сюда')
with cond:
print('condition')
cond.wait() #зависаем здесь?
print('и тут дождались') #не печатается эта строка
if __name__ == '__main__':
condition = Condition()
new_process = Process(target=reader, args=(condition,))
new_process.start()
time.sleep(3)
new_process1 = Process(target=writer1, args=(condition,))
new_process1.start()
Ответы (1 шт):
Для того чтоб и ждать и посылать уведомления с помощью Condition нужно сначала захватить блокировку ассоциированную с этим Condition.
При ожидании вы это делаете:
with cond:
...
cond.wait()
Нужно то же самое делать и при уведомлении:
with cond:
cond.notify () #что-то не так
Еще не хватает ожидания в конце:
new_process.join()
new_process1.join()
Без этого главный поток выходит и хотя запущенные процессы остаются, созданный Condition может быть не совсем в рабочем состоянии, т.к. он уже вышел из области видимости. Особенно это видно во втором процессе из-за того, что второй процесс стартует с задержкой. multiprocess.Condition использует файл для хранения какой-то информации, и при завершении основного скрипта, файл очевидно удаляется и второй процесс не может получить свой параметр.