Хотя этой теме уже почти 2 года, у меня возникла похожая проблема:
У меня есть система типа производитель / потребитель, основанная на модуле очереди. Метод выполнения моего рабочего класса определен так:
def run(self):
while True:
a, b, c = Worker._Queue.get()
# do some stuff
...
self.notify() # notify observers
Worker._Queue.task_done()
Основной класс определяет метод обновления для уведомления работника о сборе данных и их сохранения в словаре. Поскольку несколько потоков могут изменить словарь в главном классе, этот «критический раздел» заблокирован
def update(self, worker):
Main.indexUpdateLock.acquire()
# get results of worker
index = worker.getIndex()
# copy workers index into the main index
try:
for i in index:
if i in self._index:
self._index[i] += index[i]
else:
self._index[i] = index[i]
finally:
# index copied - release the lock
Main.indexUpdateLock.release()
Теперь это работает в большинстве случаев - но иногда как-то «для i in index:» в методе обновления Main выдает RuntimeError: dictionary, изменяющий размер во время итерации. indexUpdateLock определяется как threading.Lock () или threading.RLock () - поведение не изменяется ни в коем случае, если я его определяю.
для i в dict (index): действительно решает проблему, но поскольку индекс может содержать несколько тысяч записей, его копирование на самом деле не увеличивает производительность, поэтому я пытаюсь скопировать эти значения напрямую.
Хотя обновление определено в Main, посредством вызова notify () в потоке работника, обновление должно выполняться и в потоке работника, и, следовательно, task_done () будет выполняться только после завершения notify () или более поздней версии update (). обработка. И благодаря определению критической секции только одна нить может одновременно выполнять эту область - или у меня есть некоторые логические ошибки здесь? Я действительно не вижу, откуда происходит изменение индекса работника, так как единственный доступ к индексу находится в Main.update () и в Worker, но до тех пор, пока task_done () не выполнится, никакой другой метод не изменяет индекс внутри Worker
редактировать:
Хорошо, исправлена проблема, которая была вызвана HTMLParser внутри Worker, который отправил одну дополнительную запись, хотя источник был уже закрыт - хотя странное поведение. Хотя для i в index: все еще выдает ошибки для i в index.keys (): нет, поэтому я буду придерживаться этого