2014-10-16 2 views
1

Я очень новичок в многопоточности. У меня есть 2 функции в моем скрипте python. Одна функция enqueue_tasks выполняет итерацию через большой список мелких предметов и выполняет задачу по каждому элементу, который включает в себя добавление элемента в список (позволяет называть его master_list). Это у меня уже многопоточное использование фьючерсов.Могу ли я работать с двумя многопоточными функциями одновременно?

executor = concurrent.futures.ThreadPoolExecutor(15) # Arbitrarily 15 
futures = [executor.submit(enqueue_tasks, group) for group in grouper(key_list, 50)] 
concurrent.futures.wait(futures) 

У меня есть еще одна функция, которая process_master перебирает выше master_list и проверяет состояние каждого элемента в списке, а затем выполняет некоторые операции.

Могу ли я использовать тот же метод выше, чтобы использовать многопоточность для process_master? Кроме того, могу ли я запустить его в то же время, что и enqueue_tasks? Каковы последствия этого? process_master зависит от списка от enqueue_tasks, так что будет запущено их в то же время быть проблемой? Есть ли способ немного задержать вторую функцию? (возможно, time.sleep)?

ответ

1

Нет, это не безопасно. Если enqueue_tasks и process_master работают одновременно, вы можете добавить объекты в master_list внутри enqueue_tasks одновременно process_master выполняет итерацию по нему. Изменение размера итерации при переходе по ней вызывает неопределенное поведение в Python, и его всегда следует избегать. Вы должны использовать threading.Lock для защиты кода, который добавляет элементы в master_list, а также код, который выполняет итерации свыше master_list, чтобы они никогда не запускались одновременно.

Еще лучше, используйте Queue.Queue (queue.Queue в Python 3.x) вместо list, который представляет собой потокобезопасную структуру данных. Добавить предметы в Queue в enqueue_tasks и get изделия из Queue в process_master. Таким образом, process_master может безопасно работать в то же время, что и enqueue_tasks.

+0

Ah Queue.Queue кажется действительно приятным - мне не нужно было бы внедрять какие-либо механизмы ручного блокирования, если использовать его тогда? Кроме того, если я использую две многопоточные операции в одном скрипте, как мне следует выбирать количество потоков? Я выбрал здесь 15 произвольно, но если у меня есть два процесса, я должен делать 7 для каждого? Здесь моя логика испорчена? – jeffrey

+1

@jeffrey Правильно, с 'Queue.Queue' не требуется блокировка. Количество потоков, которые вы должны выбрать (и должно ли вы использовать 'ThreadPoolExecutor' или' ProcessPoolExecutor'), зависит от того, что вы делаете в 'enqueue_tasks' и' process_master'. Если вы выполняете работу с процессором, вы должны использовать процессы ProcessPoolExecutor, 'multiprocessing.Queue' и' multiprocessing.cpu_count() '. – dano

+1

@jeffrey Из-за блокировки глобального перехватчика (GIL) только один поток Python может выполняться одновременно, поэтому вы не получаете каких-либо преимуществ от многопоточности, если выполняете задачи, связанные с CPU. Использование нескольких процессов вместо потоков работает вокруг ограничений GIL. GIL может быть выпущен во время блокировки ввода-вывода, поэтому потоки по-прежнему полезны для этого. – dano

Смежные вопросы