При помещении потока для сна, пока не происходит событие X

Я пишу во многие файлы в потоковом приложении, и я создаю один обработчик на файл. У меня есть класс 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]

Я полагаю, что это покрывает сон и извлечение обработчика успешно, но я не уверен, как разбудить все потоки или еще лучше разбудить определенный поток.

6
задан Mark Amery 30 April 2015 в 19:18
поделиться

3 ответа

То, что вы ищете, называется условной переменной.

Переменные условия

Здесь ссылка на библиотеку Python 2.
Для Python 3 его можно найти здесь

6
ответ дан 16 December 2019 в 21:36
поделиться

Похоже, вам нужен threading.Semaphore , связанный с каждым обработчиком (другие объекты синхронизации, такие как События и Условия, также возможны, но Семафор кажется наиболее простым для ваших нужд). (В частности, используйте BoundedSemaphore : для вашего варианта использования, это немедленно вызовет исключение для ошибок программирования, которые по ошибке высвобождают семафон больше раз, чем получают его - и это как раз причина того, что ограниченная версия семафонов ;-).

Инициализируйте каждый семафор значением 1 при его построении (это означает, что обработчик доступен). Каждый вызов использующего потока получает на семафоре, чтобы получить обработчик (который может его заблокировать), и освобождает на нем, когда он завершается с обработчиком (что разблокирует ровно один из ожидающие потоки). Это проще, чем жизненный цикл получения / ожидания / уведомления / выпуска условия, и более надежен в будущем, поскольку, как говорится в документации для Condition:

Текущая реализация пробуждает ровно один поток, если таковой имеется ждут. Однако полагаться на такое поведение небезопасно. В будущем оптимизированная реализация может время от времени пробуждать более одного потока.

в то время как с семафором вы играете осторожно (семантика безопасна, на которую можно полагаться: если семафор инициализирован значением N, всегда есть значения от 0 до N-1 [[[ включены]] потоки, которые успешно получили семафор, но еще не выпустили его).

2
ответ дан 16 December 2019 в 21:36
поделиться

Вы действительно понимаете, что Python имеет гигантскую блокировку, так что вы не получаете большинства преимуществ многопоточности, верно?

Если только нет. является какой-то причиной, по которой главный поток должен что-то делать с результатами каждого рабочего, вы можете подумать о том, чтобы просто разветвлять другой процесс для каждого запроса. Тогда вам не придется сталкиваться с проблемами блокировки. Пусть дети сделают то, что им нужно, а затем умрут. Если им действительно нужно связаться, сделайте это по каналу, с помощью XMLRPC или через базу данных sqlite (которая является потокобезопасной).

0
ответ дан 16 December 2019 в 21:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: