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

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

1.8 Middle🔥 191 комментариев
#Python Core

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

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

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

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

Многозадачность — это способность системы выполнять несколько задач одновременно или квазиодновременно. В Python существует несколько фундаментально разных типов.

1. Многопроцессность (Multiprocessing) — истинный параллелизм

Это настоящий параллелизм — разные процессы работают на разных ядрах процессора:

from multiprocessing import Process, cpu_count
import time

def cpu_intensive_task(n):
    """Задача, требующая вычислений"""
    result = 0
    for i in range(n):
        result += i ** 2
    return result

def multiprocessing_example():
    """Истинный параллелизм на разных ядрах"""
    processes = []
    start = time.time()
    
    # Создаём процесс для каждого ядра
    for i in range(cpu_count()):
        p = Process(target=cpu_intensive_task, args=(100_000_000,))
        processes.append(p)
        p.start()
    
    for p in processes:
        p.join()
    
    print(f"Multiprocessing: {time.time() - start:.2f}s")
    # На 4-ядерной машине: ~5 сек (истинный параллелизм)

multiprocessing_example()

Характеристики:

  • Настоящий параллелизм (разные ядра)
  • Каждый процесс имеет свой GIL
  • Отличная для CPU-bound задач
  • Высокий overhead (создание процесса дорого)

2. Многопоточность (Multithreading) — конкуренция на одном ядре

Несколько потоков в одном процессе, GIL позволяет переключаться между ними:

from threading import Thread, current_thread
import time

def io_bound_task(url):
    """I/O задача"""
    print(f"Thread {current_thread().name} starting")
    time.sleep(2)  # Имитируем сетевой запрос
    print(f"Thread {current_thread().name} done")
    return f"Data from {url}"

def multithreading_example():
    """Конкуренция — потоки квазиодновременно"""
    threads = []
    start = time.time()
    
    urls = ['api1', 'api2', 'api3', 'api4']
    for url in urls:
        t = Thread(target=io_bound_task, args=(url,), name=f"Fetcher-{url}")
        threads.append(t)
        t.start()
    
    for t in threads:
        t.join()
    
    print(f"Multithreading: {time.time() - start:.2f}s")
    # ~2 сек (потоки работают одновременно в I/O операциях)

multithreading_example()

Характеристики:

  • Конкуренция, а не параллелизм
  • Один GIL на весь процесс
  • Хорошо для I/O-bound задач
  • Низкий overhead (потоки дешевле чем процессы)

3. Асинхронность (Async/Await) — кооперативная многозадачность

Один поток, но код переключается между корутинами явно:

import asyncio
import time

async def async_io_task(name, delay):
    """Асинхронная задача"""
    print(f"{name} starting")
    await asyncio.sleep(delay)  # Даёт контроль другим корутинам
    print(f"{name} done")
    return f"Result from {name}"

async def async_example():
    """Кооперативная многозадачность"""
    start = time.time()
    
    # Все корутины в одном потоке
    tasks = [
        async_io_task('Task1', 2),
        async_io_task('Task2', 2),
        async_io_task('Task3', 2),
        async_io_task('Task4', 2),
    ]
    
    results = await asyncio.gather(*tasks)
    print(f"AsyncIO: {time.time() - start:.2f}s")
    # ~2 сек (одновременно на одном потоке!)

asyncio.run(async_example())

Характеристики:

  • Кооперативная многозадачность
  • Один поток, один GIL
  • Максимальная эффективность для I/O
  • Минимальный overhead

4. Квантование времени (Time Slicing)

ОС переключает потоки через определённые интервалы:

import threading
import time

def task_with_time_slicing(task_id):
    """Задача, которая будет прерываться ОС"""
    for i in range(3):
        print(f"Task {task_id}: step {i}")
        time.sleep(0.1)  # Имитируем работу
        # ОС может переключить контекст здесь

def time_slicing_example():
    """Операционная система переключает между потоками"""
    threads = []
    
    for i in range(3):
        t = threading.Thread(target=task_with_time_slicing, args=(i,))
        threads.append(t)
        t.start()
    
    for t in threads:
        t.join()

time_slicing_example()

Это основа многопоточности — каждый поток получает квант времени.

5. Событийная многозадачность (Event-driven)

Задачи запускаются в ответ на события:

from typing import Callable, Dict, List

class EventLoop:
    """Простой event loop"""
    
    def __init__(self):
        self.handlers: Dict[str, List[Callable]] = {}
        self.queue = []
    
    def on(self, event: str, handler: Callable):
        """Подписаться на событие"""
        if event not in self.handlers:
            self.handlers[event] = []
        self.handlers[event].append(handler)
    
    def emit(self, event: str, data=None):
        """Вызвать обработчики события"""
        if event in self.handlers:
            for handler in self.handlers[event]:
                handler(data)
    
    def run(self):
        """Запустить event loop"""
        print("Event loop running...")
        while True:
            pass  # Слушаем события

# Использование
event_loop = EventLoop()

def on_user_created(user_data):
    print(f"User created: {user_data}")

def on_user_deleted(user_id):
    print(f"User deleted: {user_id}")

event_loop.on('user_created', on_user_created)
event_loop.on('user_deleted', on_user_deleted)

# Эмитируем события
event_loop.emit('user_created', {'id': 1, 'name': 'John'})
event_loop.emit('user_deleted', 123)

6. Зелёные потоки (Green Threads) — очень лёгкие потоки

Ось использует встроенные зелёные потоки (как в gevent):

from gevent import spawn, joinall
import gevent
import requests

def fetch(url):
    """Зелёный поток"""
    print(f"Fetching {url}")
    response = requests.get(url)
    print(f"Got {url}")
    return response.status_code

def green_threads_example():
    """Зелёные потоки — очень дешевые"""
    urls = [
        'http://example.com',
        'http://google.com',
        'http://github.com',
        'http://stackoverflow.com',
    ]
    
    # Создаём зелёные потоки
    greenlets = [spawn(fetch, url) for url in urls]
    
    # Ждём завершения
    joinall(greenlets)

green_threads_example()

Зелёные потоки очень лёгкие — можно создать тысячи.

Сравнение всех видов

# Таблица сравнения
print("""
┌─────────────────┬──────────┬─────────┬─────────┬────────┐
│ Тип             │ Параллл  │ Одновр  │ GIL     │ Память │
├─────────────────┼──────────┼─────────┼─────────┼────────┤
│ Процессы        │ Да       │ Да      │ Нет     │ Много  │
│ Потоки          │ Нет      │ Да      │ Да      │ Мало   │
│ AsyncIO         │ Нет      │ Да      │ Да      │ Очень  │
│ Зелёные потоки  │ Нет      │ Да      │ Да      │ Мало   │
│ Event-driven    │ Нет      │ Да      │ Да      │ Мало   │
└─────────────────┴──────────┴─────────┴─────────┴────────┘
""")

Практические рекомендации

# 1. CPU-bound (вычисления)
from multiprocessing import Pool

with Pool(4) as p:
    results = p.map(expensive_calculation, data)

# 2. I/O-bound (сеть, БД, файлы) — AsyncIO
import asyncio

await asyncio.gather(*tasks)

# 3. I/O-bound (если не можешь использовать async)
from concurrent.futures import ThreadPoolExecutor

with ThreadPoolExecutor(max_workers=5) as executor:
    results = executor.map(blocking_io, data)

# 4. Когда нужны тысячи лёгких операций
from gevent import spawn, joinall

greenlets = [spawn(task, item) for item in items]
joinall(greenlets)

Когда использовать что

# Выбор стратегии многозадачности

if task_type == "CPU_BOUND":
    # Вычисления, обработка данных
    use("multiprocessing")

elif task_type == "IO_BOUND":
    if can_use_async:
        # Сеть, БД (асинхронные драйверы)
        use("asyncio")
    else:
        if light_operations:
            # Много лёгких операций
            use("green_threads")
        else:
            # Блокирующий I/O
            use("threading")

elif task_type == "EVENT_DRIVEN":
    # Обработка событий
    use("event_loop")

Итоговый ответ

Основные виды многозадачности:

  1. Многопроцессность — истинный параллелизм на разных ядрах (CPU-bound)
  2. Многопоточность — конкуренция в одном процессе (I/O-bound)
  3. AsyncIO — кооперативная многозадачность (I/O-bound, эффективнее потоков)
  4. Квантование времени — ОС переключает между потоками
  5. Event-driven — задачи на события (используется в веб-фреймворках)
  6. Green threads — очень лёгкие потоки (много параллельных операций)

Выбор зависит от типа задачи:

  • Вычисления → многопроцессность
  • I/O → asyncio (лучше) или многопоточность
  • События → event loop
  • Много лёгких операций → зелёные потоки