Ответ
Модуль threading
в Python позволяет выполнять код конкурентно, запуская несколько потоков выполнения в рамках одного процесса. Он наиболее эффективен для I/O-bound задач.
Преимущества:
- Эффективность для I/O-операций: Идеально подходит для задач, где программа ожидает внешние ресурсы (например, ответ от сервера, чтение файла с диска). Пока один поток заблокирован ожиданием, другой может выполняться.
- Общая память: Все потоки одного процесса имеют доступ к общей памяти, что упрощает обмен данными между ними (хотя и требует синхронизации).
- Отзывчивость интерфейса: В GUI-приложениях позволяет выполнять долгие операции в фоновом потоке, не замораживая основной интерфейс.
Недостатки:
- Global Interpreter Lock (GIL): Главное ограничение. GIL не позволяет нескольким потокам выполнять Python-байткод одновременно на разных ядрах CPU. Из-за этого
threading
не ускоряет CPU-bound задачи (вычисления). - Состояния гонки (Race Conditions): При одновременном доступе нескольких потоков к общим данным могут возникать непредсказуемые ошибки. Требуется использование примитивов синхронизации (
Lock
,Semaphore
и т.д.). - Сложность отладки: Ошибки в многопоточном коде часто трудно воспроизвести из-за недетерминированного порядка выполнения потоков.
Пример (симуляция I/O-задачи):
import threading
import time
def fetch_data(source):
print(f"Начинаю загрузку из {source}...")
time.sleep(2) # Симуляция ожидания ответа от сети
print(f"Загрузка из {source} завершена.")
# Потоки запустятся почти одновременно и будут 'ждать' параллельно
thread1 = threading.Thread(target=fetch_data, args=["API_1"])
thread2 = threading.Thread(target=fetch_data, args=["DB_2"])
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print("Все задачи выполнены.") # Выполнится примерно через 2 секунды, а не 4
Ключевой вывод: Используйте threading
для I/O-bound задач (сеть, файлы) и multiprocessing
для CPU-bound задач (математические расчеты), чтобы обойти ограничения GIL.