Сегодня разберемся как обстоят дела в языках программирования с точки зрения моделей многопоточности. Рассмотрим какие модели в принципе существуют:
🔵 1 to 1 (потоки выполнения на уровне ядра)
Если коротко - в такой модели каждый созданный пользователем поток исполнения соответствует одному потоку исполнения на уровне ядра. Самый примитивный вариант который возможен с точки зрения реализации.
Преимущества использования:
- Настоящий параллелизм, при наличии многоядерного процессора.
- Управление тредом берет на себя ОС и ядро. Меньше логики в приложении. Из коробки получаем вытесняюшую многозадачность и переключения.
Недостатки:
- Масштабируемость. При наличии большого количества потоков оверхэд на переключение высокий, так как нужно задействовать ОС.
- Оверхэд на создание. Создание потока требует приличного количества ресурсов, программисту требуется отслеживать количество тредов которое потенциально может создать программа, чтобы не улететь в Out Of Memory.
Где реализован:
- Язык C и библиотека
pthreads.- Python пакет
threading- Ruby пакет
thread- Java пакет
java.lang.Thread- Rust
std::thread🔵 M to 1 (потоки выполнения на уровне пользователя)
Преимущества:
- Оверхэд на создание и переключение контекста ниже чем у варианта 1-1. ОС вообще не знает о том что в программе есть свои потоки. За счет этого в определенных сценариях можно добиться повышения производительности и снижения количества потребляемых ресурсов.
Недостатки:
- Отсутствие параллелизма, даже если ресурсы машины позволяют.
- Возможность заблокировать всю программу одним неудачно созданным user space потоком.
Примеры:
Из примеров которые я знаю это Java Green Threads (Legacy). Больше мне примеров неизвестно. В каком то смысле можно реализовать подобную модель через
- задачи в
asyncio (CPython)- fiberы с использованием
async в (Ruby MRI). Так как многозадачность (в этих библиотеках) реализована как кооперативная и используется только один настоящий поток на уровне ядра то мы получаем теже преимущества и недостатки описанные выше. Также подмечу что я не просто так указал вместо языков рантаймы. Подобное сравнение имеет смысл только когда используется рантайм с GIL, ограничивающий работу программы одним ядром.
🔵 M to N (гибридная модель)
Модель которая объединяет оба подхода в елиное целое.
Преимущества:
- Параллелизм: несколько потоков ядра могут работать на нескольких процессорах, обеспечивая настоящий параллелизм.
- Гибкость: количество потоков ядра можно оптимизировать в зависимости от рабочей нагрузки, обеспечивая баланс между накладными расходами и производительностью.
- Эффективная блокировка: если один поток пользовательского уровня блокируется, другие потоки могут продолжать выполняться, поскольку их можно сопоставить с другими потоками ядра.
Недостатки:
- Сложность: Модель сложнее для реализации и управления. Система выполнения должна эффективно отображать и планировать потоки между пользовательским пространством и пространством ядра.
Примеры:
-
Java virtual threads-
Golang goroutines-
Erlang lightweight processes-
Rust (async-std, tokio)Вот такой обзор получился, спасибо что читали, пишите вопросы в комментарии, если что-то осталось непонятное. Любая поддержка постов приветствуется😊
-----
Напоминаю, что моя личка открыта для всех, а если в личку неудобно то можно написать через Google Forms.
Предлагайте темы для будущих постов, задавайте вопросы или оставляйте отзывы/пожелания.😊