Что мы называем JS async «цепями исполнения»?

1

В Java у нас есть "потоки", в CPython есть потоки (неконкурентные) и "процессы".

В JS, когда я начинаю async функцию или метод, как я официально отношусь к этим "целям выполнения кода"?

Я слышал, что каждый такой блок кода выполняется от начала до конца *, а это означает, что в JS никогда не происходит одновременной обработки **. Я не совсем уверен, что это та же ситуация, что и в потоках CPython. Лично я не решаюсь использовать "поток" для того, что у нас есть в JS, поскольку эти "нити" настолько отличаются от параллельных потоков Java.


* Просто пояснить в свете Стивена Клири полезный ответ: я имею в виду "каждый такой синхронный блок кода". Очевидно, что если await ожидание, управление будет выпущено...

** И, очевидно, никогда никакой "истинной параллельной" обработки. Я следую широко признанному различию между "параллельными" (только один поток в любой момент времени, но одна "цепочка выполнения" может уступить место другому) и "параллельно" (несколько процессов, реализующих истинную параллельную обработку, часто используя множественные Процессоры или ядра или процессы). Я понимаю, что эти "нити" в JS даже не параллельны: когда один метод AJAX или Promise или метод/функция async начинают выполняться, ничего не может произойти до тех пор, пока он не завершится (или await произойдет)...

  • 0
    Я никогда не слышал этот термин.
Теги:
multithreading
asynchronous

2 ответа

0
Лучший ответ

На сегодняшний день 24 человека, не более того, решили посмотреть на это.

FWIW, и если кто-нибудь из эксцентриков проявит интерес к этому вопросу в один прекрасный день, я предлагаю "веревки нитей" или просто "нити"... они свистят браузерный движок JS, он появится и просто не отпустит, если только они встретить await.

Я разрабатываю это приложение, где три "нити" работают более или менее одновременно, все из которых связаны с вызовами AJAX и запросом базы данных... но на самом деле это очень предпочтительно, если 2-й из 3 выполняет и возвращает до 3-го.

Но поскольку 3-й запрос для MySQL намного проще, чем второй, прежний имеет тенденцию к возврату из своей "экскурсии" AJAX совсем немного раньше, если всем разрешено работать с неограниченной асинхронностью. Это приводит к большой задержке до того, как 2-ю нитку разрешено делать свои вещи. Чтобы заставить код выполнить и завершить вторую "нить", поэтому требуется довольно много принуждения, используя async и await.

Я прочитал один комментарий по асинхронности JS где-то, где кто-то предположил, что то, как все работает в JS, означает, что вам "никогда не придется беспокоиться о проблемах параллелизма и т.д.". Я не согласен: если вы на самом деле не знаете, когда await будет разблокировано, это обязательно означает, что задействован параллелизм. Возможно, "свисающие нити" легче справляются, чем истинный "параллелизм", не говоря уже о истинном "параллелизме", однако...?

1

В JS, когда я начинаю асинхронную функцию или метод, как я официально отношусь к этим "целям выполнения кода"?

Из-за отсутствия лучшего термина я назвал их "асинхронными операциями".

Я слышал, что каждый такой блок кода выполняется от начала до конца

Это было верно... await. Теперь есть несколько способов подумать об этом, оба из которых верны:

  • Блоки кода выполняются исключительно, если не await.
  • await разбивает свою функцию на несколько кодовых блоков, которые выполняют исключительно (каждый await это "точка разделения").

это означает, что в JS никогда не происходит параллельной обработки.

Я бы не согласился с этим утверждением. JavaScript усиливает асинхронность (до async/await, он использовал обратные вызовы или обещания), поэтому он имеет асинхронный параллелизм, хотя и не параллельный параллелизм.

Хорошая ментальная модель заключается в том, что JavaScript по сути является однопоточным, и один поток имеет очередь работы. await не блокирует этот поток; он возвращается, и когда его thenable/Promise завершается, он планирует оставшуюся часть этого метода ("продолжение") в очередь.

Таким образом, вы можете одновременно выполнять несколько асинхронных методов. Именно так Node.js обрабатывает несколько одновременных запросов.

Мое понимание заключается в том, что эти "нити" в JS даже не параллельны: когда один метод AJAX или Promise или метод/функция async начинают выполняться, ничего не может произойти до тех пор, пока оно не закончится...

Нет, это неверно. await вернет управление в основной поток, освободив его для выполнения другой работы.

то, как все работает в JS, означает, что вам "никогда не придется беспокоиться о проблемах параллелизма и т.д."

Ну... да и нет. Поскольку JavaScript по сути является однопоточным, никогда не возникает конкуренции над данными, разделяемыми между несколькими потоками (очевидно). Я бы сказал, о чем думал первоначальный писатель. Поэтому я бы сказал, что к северу от 90% проблем с синхронизацией потоков просто уйти.

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

В идеале лучшим решением является переход к более функциональному мышлению, то есть избавление от общего состояния как можно больше. Асинхронные операции должны возвращать свои результаты вместо обновления общего состояния. Затем эти параллельные асинхронные операции могут быть составлены в асинхронном режиме более высокого уровня с использованием async, await и Promise.all. Если это возможно, этот более функциональный подход к возврату, а не к состоянию и композиции функции сделает код более удобным для решения.

Но все же есть ситуации, когда это невозможно. Возможно разработать асинхронные эквиваленты классических синхронных координационных примитивов. Я разработал концептуальную концепцию AsyncLock, но не могу найти код где-нибудь. В любом случае, это возможно.

  • 0
    Э-э ... да, мое понимание точно такое же, как и ваше. В моем комментарии о «параллелизме, а не в проблеме» я цитировал кого-то еще и говорил, что они ошибаются. Конечно, подождите, await руки вернутся к двигателю JS, и позволит продолжить работу еще одной нити. Когда вы говорите «это неправильно», это неправильное понимание того, что я говорил: весь синхронный код в JS «перегружает» движок JS. Вот почему я говорю, что это даже не «одновременный» в истинном смысле: движок JS не может ничего делать, кроме как обрабатывать цепочку синхронного кода, пока эта цепочка не перестанет «зависать», возможно, из-за await .
  • 0
    Сравните это с CPython, где, хотя интерпретатор не способен к достижению параллелизма (в рамках одного и того же процесса), я считаю, что он способен переключаться с обработки одного потока на другой без явного сигнала в коде (т. await ) ... что, на мой взгляд, таким образом квалифицируется как истинное совпадение. В отличие от JS. И именно поэтому вы можете иметь общее состояние в CPython, о котором вам нужно беспокоиться гораздо больше, чем в JS!
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню