Асинхронное программирование vs многопоточность и многопроцессорность

Введение: Зачем нужны разные подходы? 🤔

Когда Python-программа сталкивается с задачами, требующими ожидания (например, запросы к API, чтение файлов, операции с БД), её производительность падает. Тут на помощь приходят три подхода:

  1. Многопоточность (threading) — легковесные потоки в рамках одного процесса.
  2. Многопроцессорность (multiprocessing) — отдельные процессы с изолированной памятью.
  3. Асинхронность (asyncio) — кооперативная многозадачность в одном потоке.

Многопоточность: Быстро, но с оговорками 🧵

Потоки делят память процесса и выполняются почти параллельно. Однако из-за GIL (Global Interpreter Lock) в Python только один поток исполняет байткод в момент времени.

import threading
import time

def download_file(url):
    print(f"Начинаем загрузку {url}...")
    time.sleep(2)  # Имитация долгой операции
    print(f"Загрузка {url} завершена!")

threads = []
for url in ["url1", "url2", "url3"]:
    thread = threading.Thread(target=download_file, args=(url,))
    thread.start()
    threads.append(thread)

for thread in threads:
    thread.join()

Плюсы:

  • Подходит для I/O-bound задач (сетевые запросы, работа с диском).
  • Легче, чем процессы (меньше накладных расходов).

Минусы:

  • GIL ограничивает эффективность для CPU-bound задач.
  • Риск race conditions (нужны блокировки).

Многопроцессорность: Настоящий параллелизм 🚀

Каждый процесс работает в своём адресном пространстве, обходя ограничения GIL. Идеально для CPU-heavy операций.

from multiprocessing import Process

def calculate_factorial(n):
    result = 1
    for i in range(1, n+1):
        result *= i
    print(f"Факториал {n} вычислен")

processes = []
for num in [50000, 60000, 70000]:
    proc = Process(target=calculate_factorial, args=(num,))
    proc.start()
    processes.append(proc)

for proc in processes:
    proc.join()

Плюсы:

  • Полноценное использование многоядерных процессоров.
  • Изоляция памяти между процессами (меньше риск взаимного влияния).

Минусы:

  • Высокие накладные расходы на создание.
  • Сложнее обмениваться данными (Queue, Pipe).

Асинхронность: Однопоточный параллелизм ⚡

Асинхронный код работает в одном потоке, переключаясь между задачами при ожидании. Использует ключевые слова async/await.

import asyncio

async def fetch_data(url):
    print(f"Начало загрузки: {url}")
    await asyncio.sleep(2)  # Неблокирующее ожидание
    print(f"Данные из {url} получены")

async def main():
    tasks = [
        fetch_data("api1.com"),
        fetch_data("api2.com"),
        fetch_data("api3.com")
    ]
    await asyncio.gather(*tasks)

asyncio.run(main())

Плюсы:

  • Нет накладных расходов на потоки/процессы.
  • Идеально для высоконагруженных I/O-приложений (веб-серверы).

Минусы:

  • Не подходит для CPU-bound задач.
  • Требует переписывания кода под async/await.

Сравнение в таблице 📊

Критерий Многопоточность Многопроцессорность Асинхронность
Параллелизм Псевдо Да Кооперативный
Потребление памяти Низкое Высокое Очень низкое
Подходит для I/O-bound CPU-bound I/O-bound
Сложность отладки Средняя Высокая Высокая

Как выбрать? Практические советы от Данилы Бежина 🔥

  1. CPU-bound задачи (видеообработка, ML) → multiprocessing.
  2. Много I/O-операций (веб-скрапинг, API) → asyncio или threading.
  3. Legacy-кодthreading (минимальные изменения).
  4. Микросервисы на FastAPIasyncio (нативная поддержка).

Подробнее о тонкостях — в разборе Данилы на YouTube.


Пример: Сравнение производительности ⏱️

Допустим, нам нужно сделать 100 HTTP-запросов. Вот как справятся разные подходы:

  1. Синхронный код: ~100 сек (последовательно).
  2. Потоки: ~5 сек (ограничено GIL и накладными расходами).
  3. Асинхронный код: ~2 сек (оптимально для сетевых операций).

Итоги: Главное — баланс ⚖️

Нет «серебряной пули» — каждый подход решает свои задачи. Сочетание инструментов (например, asyncio + multiprocessing) иногда даёт лучший результат. Экспериментируйте и замеряйте производительность! 🧪

Скрыть рекламу навсегда

📘 VK Видео — обучение без ограничений

Все уроки доступны без VPN, без блокировок и зависаний.

Можно смотреть с телефона, планшета или компьютера — в любое время.

▶️ Смотреть на VK Видео