Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

AI info

Карта сайта

Документы

Медиа

Назад
Вопрос про Python: threading, async, await, concurrency, GIL, asyncio

В чем разница между threading и async/await?

Вопрос проверяет понимание двух основных подходов к параллельному выполнению задач в Python и помогает оценить, когда использовать многопоточность, а когда асинхронность.

Короткий ответ

Threading использует несколько потоков выполнения внутри одного процесса, переключаемых операционной системой, но в Python из-за GIL (Global Interpreter Lock) они не выполняют Python-код одновременно на нескольких ядрах CPU, что делает их полезными в основном для задач, связанных с ожиданием ввода-вывода (I/O-bound). Async/await — это модель кооперативной многозадачности, где одна задача явно передает управление другой, когда ей нужно ждать; она идеально подходит для высоконагруженных I/O-приложений, таких как веб-серверы, так как создает меньше накладных расходов, чем потоки.

Длинный ответ

В Python существует два основных подхода для организации параллельного выполнения задач, связанных с ожиданием: многопоточность (threading) и асинхронное программирование с async/await. Хотя оба подхода позволяют выполнять несколько операций "одновременно", они работают на разных принципах и имеют разные области применения.

Многопоточность (Threading)

Модуль threading создает потоки выполнения внутри одного процесса. Потоки управляются операционной системой, которая сама решает, когда переключаться между ними (вытесняющая многозадачность). Однако в Python существует GIL (Global Interpreter Lock), который предотвращает одновременное выполнение Python-байткода несколькими потоками в одном процессе. Это означает, что для CPU-интенсивных задач (CPU-bound) многопоточность не даст прироста производительности на многоядерных системах. Потоки полезны для задач, связанных с ожиданием ввода-вывода (I/O-bound), например, чтения файлов или сетевых запросов, потому что пока один поток ждет ответа, GIL может быть передан другому потоку, который готов выполнять работу.

Асинхронность с async/await

Асинхронное программирование, реализованное в модуле asyncio, использует модель кооперативной многозадачности. Здесь существует только один поток, но множество задач (coroutines). Задача явно передает управление (используя ключевое слово await), когда ей нужно дождаться результата, например, ответа от сети. Это позволяет эффективно использовать время простоя, планируя выполнение других готовых задач. Такой подход создает значительно меньше накладных расходов, чем создание и переключение потоков ОС, и может обслуживать тысячи одновременных соединений.

Примеры кода

Пример с threading для скачивания нескольких URL:

import threading
import requests

def download(url):
    response = requests.get(url)
    print(f"Downloaded {url}: {len(response.content)} bytes")

urls = ["https://example.com", "https://example.org"]
threads = []
for url in urls:
    t = threading.Thread(target=download, args=(url,))
    t.start()
    threads.append(t)
for t in threads:
    t.join()
print("All downloads finished.")

Пример с asyncio для той же задачи:

import asyncio
import aiohttp

async def download(session, url):
    async with session.get(url) as response:
        content = await response.read()
        print(f"Downloaded {url}: {len(content)} bytes")

async def main():
    async with aiohttp.ClientSession() as session:
        urls = ["https://example.com", "https://example.org"]
        tasks = [download(session, url) for url in urls]
        await asyncio.gather(*tasks)
    print("All downloads finished.")

asyncio.run(main())

Ключевые различия и применение

  • Управление: Потоками управляет ОС, асинхронными задачами — цикл событий (event loop) в одном потоке.
  • Производительность: Для I/O-bound задач asyncio обычно эффективнее из-за меньших накладных расходов.
  • Сложность: Асинхронный код может быть сложнее для понимания и отладки из-за кооперативной природы.
  • Блокирующие вызовы: В асинхронном коде нельзя использовать обычные блокирующие функции (например, time.sleep или requests.get без специальных оберток), так как они заблокируют весь цикл событий.

Вывод: Используйте threading для простых I/O-задач, особенно когда нужно интегрироваться с библиотеками, которые не поддерживают asyncio. Async/await предпочтительнее для высокопроизводительных сетевых приложений (веб-серверы, клиенты API, чат-боты), где требуется обрабатывать тысячи одновременных соединений с минимальными затратами ресурсов.

  • Аватар

    Python Guru

    Sergey Filichkin

    Guru – это эксперты YeaHub, которые помогают развивать комьюнити.

Уровень

  • Рейтинг:

    4

  • Сложность:

    6

Навыки

  • Python

    Python

  • Node.js

    Node.js

Ключевые слова

#threading

#async

#await

#concurrency

#GIL

#asyncio

Подпишись на Python Developer в телеграм

  • Аватар

    Python Guru

    Sergey Filichkin

    Guru – это эксперты YeaHub, которые помогают развивать комьюнити.