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

Где исполняются потоки в Python?

2.3 Middle🔥 171 комментариев
#Python Core#Асинхронность и многопоточность

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

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

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

Где исполняются потоки в Python?

Потоки в Python исполняются в едином процессе, но управление их выполнением зависит от типа потока и механизма планирования. Разберёмся подробно.

1. Потоки ОС (OS Threads) в Python

Потоки Python — это настоящие потоки операционной системы, которые исполняются на уровне ОС, но контролируются глобальной блокировкой GIL (Global Interpreter Lock):

import threading
import time

def worker(name):
    print(f"Поток {name} начал исполнение")
    time.sleep(1)
    print(f"Поток {name} завершился")

# Создаём и запускаем потоки
thread1 = threading.Thread(target=worker, args=("A",))
thread2 = threading.Thread(target=worker, args=("B",))

thread1.start()  # Поток запускается на уровне ОС
thread2.start()

thread1.join()  # Ожидаем завершения
thread2.join()

Потоки выполняются в одном процессе, но на разных ядрах ЦПУ (если ОС позволяет), однако только один может выполнять Python-код одновременно.

2. Global Interpreter Lock (GIL)

Вот ключевый момент: потоки исполняются на уровне ОС, но GIL ограничивает одновременное выполнение байт-кода Python:

import threading
import time

def cpu_bound():
    """Вычислительно интенсивная операция."""
    total = 0
    for i in range(100_000_000):
        total += i
    return total

# С потоками (GIL)
start = time.time()
thread1 = threading.Thread(target=cpu_bound)
thread2 = threading.Thread(target=cpu_bound)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print(f"С потоками: {time.time() - start:.2f} сек")  # ~ 6-7 сек

# С обычным выполнением
start = time.time()
cpu_bound()
cpu_bound()
print(f"Последовательно: {time.time() - start:.2f} сек")  # ~ 3-4 сек

3. Где физически исполняются потоки

На уровне операционной системы:

  • Linux: потоки исполняются как отдельные задачи в одном процессе, видны в /proc/{pid}/task/
  • Windows: потоки запускаются через API CreateThread()
  • macOS: используется kernel threads через Mach API
# На Linux можно увидеть потоки
ps -eLf | grep python
# или
ls /proc/{pid}/task/  # Каждый tid — отдельный поток

4. Планирование потоков

Операционная система планирует потоки (scheduling), а Python интерпретатор контролирует доступ к GIL:

import threading
import sys

print(f"GIL включена: {hasattr(sys, getswitchinterval)}")
print(f"Интервал переключения: {sys.getswitchinterval():.4f} сек")

# Можно менять интервал переключения между потоками
sys.setswitchinterval(0.001)  # Переключаться каждые 1ms

5. GIL и многопоточность

GIL позволяет потокам параллельно работать с блокирующими операциями (I/O), но не с CPU-bound кодом:

import threading
import requests
import time

def fetch_url(url):
    """I/O операция — GIL освобождается."""
    response = requests.get(url)
    return len(response.content)

def cpu_bound():
    """CPU операция — GIL не освобождается."""
    return sum(i for i in range(10_000_000))

# Для I/O — потоки эффективны
start = time.time()
urls = ["https://example.com"] * 10
threads = [threading.Thread(target=fetch_url, args=(url,)) for url in urls]
for t in threads:
    t.start()
for t in threads:
    t.join()
print(f"I/O с потоками: {time.time() - start:.2f} сек")  # ~1-2 сек (параллельно)

# Для CPU — потоки неэффективны
start = time.time()
thread1 = threading.Thread(target=cpu_bound)
thread2 = threading.Thread(target=cpu_bound)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print(f"CPU с потоками: {time.time() - start:.2f} сек")  # ~4-5 сек (медленнее!)

6. Альтернативы потокам

Для CPU-bound задач:

from multiprocessing import Process

def cpu_bound():
    return sum(i for i in range(100_000_000))

# Используем разные процессы (нет GIL)
p1 = Process(target=cpu_bound)
p2 = Process(target=cpu_bound)
p1.start()
p2.start()
p1.join()
p2.join()

Для I/O-bound задач:

import asyncio

async def fetch_url(url):
    """Асинхронная операция — очень эффективна."""
    # await fetch(url)
    pass

async def main():
    await asyncio.gather(
        fetch_url("url1"),
        fetch_url("url2"),
    )

asyncio.run(main())

7. Практический вывод

Потоки исполняются:

  • На уровне ОС (разные ядра, если возможно)
  • В одном процессе Python
  • Под контролем GIL для CPU-bound операций
  • Параллельно для I/O-bound операций

Используй потоки для: I/O операций (сеть, файлы)

Используй процессы для: CPU-интенсивных вычислений

Используй asyncio для: множества I/O операций с минимальной памятью