Я пишу во многие файлы в потоковом приложении, и я создаю один обработчик на файл. У меня есть класс HandlerFactory, который справляется с распределением этих обработчиков. То, что я хотел бы сделать, является этим
распараллельте запросы, и получает дескриптор файла foo.txt от класса HandlerFactory
распараллельте обработчик файлов foo.txt запросов B
класс обработчика распознает, что этот дескриптор файла был проверен
класс обработчика помещает поток для сна
распараллельте дескриптор файла завершений B с помощью метода обертки от HandlerFactory
HandlerFactory уведомляет потоки сна
распараллельте следы B, и успешно получает дескриптор файла foo.txt
Это - то, что я имею до сих пор,
def get_handler(self, file_path, type):
self.lock.acquire()
if file_path not in self.handlers:
self.handlers[file_path] = open(file_path, type)
elif not self.handlers[file_path].closed:
time.sleep(1)
self.lock.release()
return self.handlers[file_path][type]
Я полагаю, что это покрывает сон и извлечение обработчика успешно, но я не уверен, как разбудить все потоки или еще лучше разбудить определенный поток.
То, что вы ищете, называется условной переменной.
Здесь ссылка на библиотеку Python 2.
Для Python 3 его можно найти здесь
Похоже, вам нужен threading.Semaphore , связанный с каждым обработчиком (другие объекты синхронизации, такие как События и Условия, также возможны, но Семафор кажется наиболее простым для ваших нужд). (В частности, используйте BoundedSemaphore : для вашего варианта использования, это немедленно вызовет исключение для ошибок программирования, которые по ошибке высвобождают семафон больше раз, чем получают его - и это как раз причина того, что ограниченная версия семафонов ;-).
Инициализируйте каждый семафор значением 1
при его построении (это означает, что обработчик доступен). Каждый вызов использующего потока получает
на семафоре, чтобы получить обработчик (который может его заблокировать), и освобождает
на нем, когда он завершается с обработчиком (что разблокирует ровно один из ожидающие потоки). Это проще, чем жизненный цикл получения / ожидания / уведомления / выпуска условия, и более надежен в будущем, поскольку, как говорится в документации для Condition:
Текущая реализация пробуждает ровно один поток, если таковой имеется ждут. Однако полагаться на такое поведение небезопасно. В будущем оптимизированная реализация может время от времени пробуждать более одного потока.
в то время как с семафором вы играете осторожно (семантика безопасна, на которую можно полагаться: если семафор инициализирован значением N, всегда есть значения от 0 до N-1 [[[ включены]] потоки, которые успешно получили семафор, но еще не выпустили его).
Вы действительно понимаете, что Python имеет гигантскую блокировку, так что вы не получаете большинства преимуществ многопоточности, верно?
Если только нет. является какой-то причиной, по которой главный поток должен что-то делать с результатами каждого рабочего, вы можете подумать о том, чтобы просто разветвлять другой процесс для каждого запроса. Тогда вам не придется сталкиваться с проблемами блокировки. Пусть дети сделают то, что им нужно, а затем умрут. Если им действительно нужно связаться, сделайте это по каналу, с помощью XMLRPC или через базу данных sqlite (которая является потокобезопасной).