Ответ
В Python существует несколько основных подходов к конкурентности, каждый из которых оптимален для разных типов задач:
-
Потоки (threading)
- Применение: Идеальны для I/O-bound задач, где выполнение блокируется ожиданием внешних операций (например, сетевые запросы, чтение/запись файлов). Python GIL (Global Interpreter Lock) ограничивает параллельное выполнение CPU-bound кода в потоках, но для I/O-bound задач потоки эффективны, так как GIL освобождается во время ожидания.
import threading import requests
def fetch_url(url): print(f"Fetching {url}...") response = requests.get(url) print(f"Finished {url} with status {response.status_code}")
urls = [ "https://www.google.com", "https://www.yandex.ru", "https://www.bing.com" ]
threads = [threading.Thread(target=fetch_url, args=(url,)) for url in urls] [t.start() for t in threads] # Запуск всех потоков [t.join() for t in threads] # Ожидание завершения всех потоков
- Применение: Идеальны для I/O-bound задач, где выполнение блокируется ожиданием внешних операций (например, сетевые запросы, чтение/запись файлов). Python GIL (Global Interpreter Lock) ограничивает параллельное выполнение CPU-bound кода в потоках, но для I/O-bound задач потоки эффективны, так как GIL освобождается во время ожидания.
-
Процессы (multiprocessing)
- Применение: Используются для CPU-bound задач, требующих интенсивных вычислений (например, обработка изображений, сложные математические расчеты). Каждый процесс имеет свой интерпретатор Python и собственное адресное пространство, что позволяет обходить ограничение GIL и использовать все ядра процессора для истинного параллелизма.
from multiprocessing import Pool import time
def heavy_computation(n):
Имитация тяжелых вычислений
sum_val = 0 for i in range(n): sum_val += i * i return sum_valif name == 'main': numbers = [107, 107, 107, 107] with Pool() as p: results = p.map(heavy_computation, numbers) print(f"Results: {results}")
- Применение: Используются для CPU-bound задач, требующих интенсивных вычислений (например, обработка изображений, сложные математические расчеты). Каждый процесс имеет свой интерпретатор Python и собственное адресное пространство, что позволяет обходить ограничение GIL и использовать все ядра процессора для истинного параллелизма.
-
Асинхронность (asyncio)
- Применение: Подход для высоконагруженных I/O-bound задач, основанный на кооперативной многозадачности и одном потоке выполнения. Позволяет эффективно обрабатывать множество одновременных операций ввода-вывода без создания большого количества потоков или процессов, используя
awaitдля неблокирующего ожидания. Идеально для сетевых приложений (веб-серверы, WebSocket, API-клиенты).import asyncio import aiohttp
async def fetch_async(url): print(f"Async fetching {url}...") async with aiohttp.ClientSession() as session: async with session.get(url) as response: print(f"Async finished {url} with status {response.status}") return await response.text()
async def main_async(): urls = [ "https://www.google.com", "https://www.yandex.ru", "https://www.bing.com" ] await asyncio.gather(*[fetch_async(url) for url in urls])
if name == 'main': asyncio.run(main_async())
- Применение: Подход для высоконагруженных I/O-bound задач, основанный на кооперативной многозадачности и одном потоке выполнения. Позволяет эффективно обрабатывать множество одновременных операций ввода-вывода без создания большого количества потоков или процессов, используя
Дополнительные аспекты:
- GIL (Global Interpreter Lock): Ключевое ограничение CPython, которое позволяет выполнять только один поток байт-кода Python за раз. Для CPU-bound задач это означает, что
threadingне дает истинного параллелизма. Обходится использованиемmultiprocessingили C-расширений. - Синхронизация: Для координации доступа к общим ресурсам в конкурентных программах используются примитивы синхронизации:
Lock,Semaphore,Event,Queue(вthreadingиmultiprocessing), а такжеasyncio.Lock,asyncio.Semaphoreиasyncio.Queueдля асинхронного кода. - Выбор подхода: Определяется типом задачи (CPU-bound vs. I/O-bound), требованиями к производительности, сложности реализации и потреблением ресурсов.