Корутины по своей сути выполняются в одном потоке. Они реализуют кооперативную многозадачность, где переключение между задачами происходит явно, когда корутина "отдает" управление с помощью ключевого слова await. В отличие от потоков, где операционная система управляет переключением, в корутинах это делает программа.
Однако, корутины могут использовать пулы потоков или процессов для выполнения блокирующих операций (например, ввод/вывод), чтобы не блокировать основной цикл событий. В таком случае, сама блокирующая операция будет выполняться в другом потоке/процессе, но ожидание ее результата происходит в том же потоке, где работает цикл событий с корутинами.
Ключевые отличия:
| Признак | Потоки (Threads) | Корутины (Coroutines) |
|---|---|---|
| Управление | Операционная система (преemptive) | Программа (cooperative) |
| Параллелизм | Истинный параллелизм (на многоядерных) | Конкурентность (один поток) |
| Переключение | Дорого (контекстное переключение ОСs) | Дешево (передача управления) |
| Использование | Блокирующие операции, CPU-bound задачи | Неблокирующие операции, I/O-bound задачи |
| Создание | Дорого | Дешево |
| Память | Больше | Меньше |
Пример асинхронной функции с использованием asyncio:
python
В данном примере fetch_data является корутиной. await asyncio.sleep(delay) передает управление циклу событий, позволяя выполнять другие задачи (в данном случае, другую корутину fetch_data с задержкой 1 секунда) в том же потоке, пока ожидается завершение "сна".
Таким образом, корутины сами по себе не создают новые потоки, но они отлично подходят для эффективного управления конкурентностью задач в рамках одного потока, особенно для I/O-bound операций, где нет интенсивного использования CPU.