Как стать автором
Обновить

Комментарии 13

Я никак не могу взять в толк. Ведь фоновая операция (к примеру обращение к БД) должна тоже в каком-то потоке обрабатываться? Где она происходит? В каком-то отдельном потоке? Но кто его создает? И каково количество этих потоков? Ведь у них же тоже должно быть переключение контекста, а значит те же сами блокировки.

При переключении задач процессору же нужно данные от предыдущей задачи сохранить. А перед этим понять в каких регистрах задача данные хранит и их где-то сохранить? Правильно? Где оно сохраняется и как это происходит? Ведь по факту это тоже самое переключение контекста только в миниатрюре.

Первое зависит от реализации. Платформа, предоставляющая event loop и асинхронное API действительно может создать сколько угодно других потоков и просто перекидывать данные оттуда в «наш главный». Но по факту новые потоки нужны только если что-то действительно вычисляем, опросить состояние IO (пример с БД) можно и в том же самом. А как там ОС это проворачивает — неизвестно, может у неё отдельный поток тоже для всего IO, я не знаю.


Второе: да, то же самое микропереключение. Только всё состояние живёт в замыканиях функций. Что, по сути, ничем не отличается от поточного контекста. Т.е. если бы мы это делали там, где нет замыканий, нам пришлось бы в функции, запрашивающие старта асинхронной операции, передавать не только коллбэк, но и какой-то объект контекста, который будет передан этому обработчику во время его вызова.

Тут важно ещё понимать, что «обращение к БД» в основном… не происходит, мы почти всё время просто ждём. Записать/прочитать данные в буффер и отправить его сетевой карте — это относительно быстрая операция, относительно времени, которое проходит между такими операциями. И если у нас времени ожидания достаточно, чтобы ещё повычислять чего-нибудь другого — нам не нужен ещё один поток.

Базовая "фоновая" IO-операция, такая как чтение или запись в сокет либо в файл, фонового потока не требует*. Она выполняется с использованием неблокироющего сокета или асинхронного API.


Более сложные фоновые задачи зависят от того, кто и как их писал. Если это внешняя библиотека (например, тот же драйвер БД) — то вполне возможно, что она будет использовать блокирующие операции, а значит вызовы надо выносить в отдельный пул потоков.


Если же задача была написана с использованием асинхронных операций — то нет никаких причин существовать дополнительному фоновому потоку во время выполнения задачи.




* говорят, в linux есть проблемы с файловым асинхронным вводом-выводом, из-за чего в некоторых конфигурациях серверу nginx приходится "выталкивать" чтение файлов в пул потоков. Но сетевой ввод-вывод, а именно он создает больше всего задержек, заставить работать полностью асинхронно не так и трудно.

во всяких там FLex'ах обычно есть еще один поток, параллельный главному, долгие операции (БД, Http) туда перекидываются.
Разработчики Python просто клепают библы на C++ к.е. запускают поток параллельный главному и перекидывают таски туда.
Но, в итоге, все равно же получается очередь сообщений между потоками, этакая микро- RabbitMQ
Может эта статья вам поможет: There Is No Thread.
Она про async/await из C#, но, думаю, принципиальной разницы тут нет.
Самое главное-то не написали.

try {
  let a = await something();
  let b = await xxxxx(a);
  // или еще что угодно - хоть последовательно, хоть параллельно
} catch (e) {
  console.log(e);
  throw e;
  // или еще что-нибудь
}


Вот это можно запихнуть в async-функцию, и оно будет работать, как ожидается. И стектрейс будет внятным!

Async-await возвращают исключения в JS, с которыми у него было туго с момента самого появления. (А также возвращают исключения в асинхронное программирование в любом другом языке.)

Внятные стектрейсы зависят только от используемой реализации обещаний (Promise). Ключевые слова async и await тут ни при чем. Нативные обещания в том же Chrome — да, дают внятные стектрейсы (в других браузерах не проверял). А вот всяческие полифилы могут и порушить все.

Написал «а внутрь неё подаётся получившееся R, либо возбуждается исключение E», но не уточнил, что исключение прямо внутри корутины возникает, ну и примера нет, спасибо.

получается асинхронность = кооперативная многозадачность решенная через event loop?

Нет, асинхронность может существовать там, где нет никакого event loop'а. Ведь ничто не мешает передать в любой поток коллбэк, который будет вызван, как что-нибудь произошло.


Кооперативная многозадачность решённая через event loop просто порождает асинхронность, а не является ей. Асинхронность — просто абстрактное понятие, описывающее процессы, которые происходят не мгновенно.

А это случайно не заблуждение отождествлять асинхронизм в глобальном его понимании с конкурентностью? На некоторых платформах(типа jvm) асинхорнизм построен на многопоточности ибо по другому там никак, но это всего лишь частный случай. Если брать ко-рутины то они там совсем по другому построены, и конкурентность там не причем.

А что мешает использовать подход с event loop на той же jvm? Почему многопоточность вдруг оказалась обязательной?

Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории