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

Что такое Green thread в Python?

2.4 Senior🔥 11 комментариев
#DevOps и инфраструктура#Django

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

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

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

Green thread в Python

Green thread (зелёный поток, зелёная нить) — это легковесный поток, который управляется не операционной системой, а самим приложением или специальной библиотекой. Это противоположность традиционным потокам ОС (OS threads), которые требуют значительных системных ресурсов и контролируются планировщиком ядра.

Различие между OS threads и Green threads

OS threads:

  • Создаются операционной системой
  • Требуют ~1-2 МБ оперативной памяти на поток
  • Планируются ядром (preemptive scheduling)
  • Мы можем создать несколько сотен такых потоков
  • Переключение контекста очень дорогое

Green threads:

  • Создаются приложением/библиотекой в пользовательском пространстве
  • Требуют ~10-100 КБ оперативной памяти на поток
  • Планируются самой программой (cooperative scheduling)
  • Мы можем создать миллионы таких потоков
  • Переключение контекста очень дешевое

Реализация Green threads в Python

Питон не имеет встроенной поддержки green threads, но есть библиотеки, которые их реализуют.

1. gevent

import gevent
from gevent import Greenlet

def worker(n):
    for i in range(5):
        print(f"Worker {n}, iteration {i}")
        gevent.sleep(0.1)  # Кооперативная точка переключения

# Создаём несколько green threads (greenlets)
greenlets = [Greenlet.spawn(worker, i) for i in range(3)]

# Ждём завершения всех
gevent.joinall(greenlets)

2. asyncio (встроенная в Python)

Встроенный модуль asyncio использует корутины, которые похожи на green threads:

import asyncio

async def worker(n):
    for i in range(5):
        print(f"Worker {n}, iteration {i}")
        await asyncio.sleep(0.1)  # Кооперативная точка переключения

async def main():
    # Создаём несколько корутин
    tasks = [worker(i) for i in range(3)]
    # Выполняем их параллельно
    await asyncio.gather(*tasks)

asyncio.run(main())

Преимущества Green threads

1. Низкие затраты памяти:

import gevent
import threading

# Green threads: можно создать миллионы
greenlets = [gevent.Greenlet.spawn(lambda: print("Hi")) for _ in range(100000)]

# OS threads: можно создать только несколько сотен
threads = [threading.Thread(target=lambda: print("Hi")) for _ in range(1000)]  # Будет ошибка

2. Быстрое переключение контекста:

import time
import gevent
from gevent import Greenlet

def task():
    pass

# Green threads переключаются очень быстро
start = time.time()
greenlets = [Greenlet.spawn(task) for _ in range(10000)]
gevent.joinall(greenlets)
green_time = time.time() - start

print(f"Green threads: {green_time:.3f}s")

3. Простое написание асинхронного кода:

import gevent
from gevent import monkey
monkey.patch_all()  # Патчим стандартные блокирующие функции

import requests

def fetch_url(url):
    response = requests.get(url)  # Выглядит как синхронный код
    return response.status_code

urls = ["https://example.com", "https://google.com"]
greenlets = [gevent.Greenlet.spawn(fetch_url, url) for url in urls]
results = gevent.joinall(greenlets, return_value=True)
print(results)

Недостатки Green threads

1. Кооперативное планирование:

import gevent
from gevent import Greenlet

def blocking_task():
    # Если нет явного yield/sleep, другие greenlets не выполняются
    for i in range(1000000000):  # Бесконечный цикл без gevent.sleep
        pass

def other_task():
    print("Я никогда не выполнюсь до завершения blocking_task!")

gevent.spawn(blocking_task)
gevent.spawn(other_task)
gevent.wait()  # Бесконечное ожидание

2. Несовместимость с многоядерностью:

import gevent
from gevent import Greenlet

def cpu_bound():
    # Green threads не могут использовать несколько ядер
    total = 0
    for i in range(100000000):
        total += i
    return total

# Оба greenlets выполняются на одном ядре, нет параллелизма
g1 = Greenlet.spawn(cpu_bound)
g2 = Greenlet.spawn(cpu_bound)

gevent.joinall([g1, g2])

3. Отладка сложнее:

# Stacktrace в green threads менее информативен
import gevent

def nested_call():
    raise ValueError("Error in nested call")

def outer_call():
    nested_call()

gevent.spawn(outer_call)
gevent.wait()  # Stacktrace может быть неполным

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

# ХОРОШО: I/O-bound операции (сеть, файлы, БД)
import gevent
import requests

def fetch_multiple_urls(urls):
    """Green threads идеальны для параллельных I/O операций"""
    greenlets = [gevent.Greenlet.spawn(requests.get, url) for url in urls]
    return gevent.joinall(greenlets, return_value=True)

# ПЛОХО: CPU-bound операции
def compute_heavy():
    """Green threads НЕ подходят для интенсивных вычислений"""
    return sum(i*i for i in range(100000000))

greenlets = [gevent.Greenlet.spawn(compute_heavy) for _ in range(4)]
gevent.joinall(greenlets)  # Медленнее, чем multiprocessing

asyncio vs gevent

# asyncio: явное указание точек переключения
import asyncio

async def task():
    #必须 использовать async/await
    await asyncio.sleep(0.1)

# gevent: автоматическое переключение (при monkey patching)
import gevent

def task():
    gevent.sleep(0.1)  # или просто time.sleep() после monkey.patch_all()

Заключение

Green threads — мощный инструмент для создания высокопроизводительных I/O-bound приложений. Они позволяют обрабатывать тысячи одновременных соединений с минимальными затратами ресурсов. Однако они не подходят для CPU-bound задач и требуют понимания кооперативного многопотока. Для современного Python-кода рекомендуется использовать встроенный asyncio, который более стандартизирован и имеет лучшую поддержку экосистемы.