← Назад к вопросам

Какие знаешь потоки многозадачности?

2.2 Middle🔥 181 комментариев
#Базы данных (NoSQL)

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Потоки многозадачности в Python

В Python существует несколько подходов к реализации многозадачности. Каждый имеет свои особенности, преимущества и ограничения. Рассмотрим основные потоки (подходы) для параллельного выполнения кода.

1. Threading (многопоточность)

Описание: Истинные потоки операционной системы (OS threads). В CPython из-за GIL выполняются квазипараллельно.

import threading
import time

def worker(name):
    print(f'Thread {name} started')
    time.sleep(2)
    print(f'Thread {name} finished')

# Создание потока
thread = threading.Thread(target=worker, args=('T1',))
thread.start()
thread.join()  # Ожидание завершения потока

Особенности:

  • Работает с OS-уровнем потоков
  • GIL (Global Interpreter Lock) блокирует выполнение сразу нескольких потоков на одном интерпретаторе
  • Хорошо для I/O-bound операций (сетевые запросы, файловые операции)
  • Плохо для CPU-bound операций

Синхронизация:

import threading

lock = threading.Lock()
counter = 0

def increment():
    global counter
    with lock:
        counter += 1

# Без lock может быть race condition

2. Multiprocessing (многопроцессность)

Описание: Отдельные процессы Python, каждый со своим интерпретатором и GIL.

import multiprocessing
import time

def worker(name):
    print(f'Process {name} started')
    time.sleep(2)
    print(f'Process {name} finished')

if __name__ == '__main__':
    process = multiprocessing.Process(target=worker, args=('P1',))
    process.start()
    process.join()

Особенности:

  • Избегает GIL - истинный параллелизм
  • Хорошо для CPU-bound операций
  • Больше памяти (каждый процесс - отдельный интерпретатор)
  • Медленнее threading из-за overhead создания процессов
  • IPC (inter-process communication) требует сериализации данных

Пулы процессов:

from multiprocessing import Pool

def square(x):
    return x * x

if __name__ == '__main__':
    with Pool(4) as pool:
        results = pool.map(square, [1, 2, 3, 4, 5])
    print(results)  # [1, 4, 9, 16, 25]

3. AsyncIO (асинхронное программирование)

Описание: Однопоточное управление множеством сопрограмм (coroutines) в одном потоке.

import asyncio

async def fetch_data(url):
    # Имитация сетевого запроса
    await asyncio.sleep(2)
    return f'Data from {url}'

async def main():
    tasks = [
        fetch_data('http://example.com/1'),
        fetch_data('http://example.com/2'),
        fetch_data('http://example.com/3'),
    ]
    results = await asyncio.gather(*tasks)
    print(results)

asyncio.run(main())

Особенности:

  • Однопоточное, но очень эффективное для I/O
  • Требует async/await синтаксис
  • Event loop управляет переключением между корутинами
  • Отлично для сетевых приложений
  • Нет race conditions, не нужны локи

4. Greenlets / Gevent

Описание: Легкие псевдопотоки (userland threads), управляемые библиотекой.

from gevent import spawn, sleep

def worker(name):
    print(f'Greenlet {name} started')
    sleep(2)
    print(f'Greenlet {name} finished')

if __name__ == '__main__':
    g1 = spawn(worker, 'G1')
    g2 = spawn(worker, 'G2')
    g1.join()
    g2.join()

Особенности:

  • Очень легкие (можно создать тысячи)
  • Автоматический context switching
  • Cooperative multitasking
  • Monkey patching для блокирующих операций

Сравнительная таблица

ПодходI/O-boundCPU-boundПамятьСложностьGIL
Threading✓✓низсреднда
Multiprocessing✓✓высвыснет
AsyncIO✓✓низвыснет
Gevent✓✓низнизда

Выбор подхода

Используй Threading:

  • I/O-bound операции (веб-скрейпинг, API запросы)
  • Простые параллельные задачи
  • Когда IPC не критичен

Используй Multiprocessing:

  • CPU-bound операции (расчеты, обработка данных)
  • Когда нужна истинная параллельность
  • Когда выгода перевешивает overhead

Используй AsyncIO:

  • Современные I/O-bound приложения
  • Веб-серверы и клиенты
  • Когда нужна максимальная производительность

Используй Gevent:

  • Когда нужна простота threading с производительностью AsyncIO
  • Для быстрого прототипирования

Комбинированный подход:

# AsyncIO + Multiprocessing для CPU-bound внутри async
import asyncio
from concurrent.futures import ProcessPoolExecutor

async def cpu_bound_async(x):
    loop = asyncio.get_event_loop()
    with ProcessPoolExecutor() as pool:
        result = await loop.run_in_executor(pool, cpu_bound_function, x)
    return result

Вывод: Выбор потока многозадачности зависит от типа задачи и требований к производительности и простоте кода.

Какие знаешь потоки многозадачности? | PrepBro