В случае параллелизма и отсутствия мультиобработки, в каком порядке выполняется код? - PullRequest
0 голосов
/ 11 июня 2018

Я создаю приложение, используя Node, и мне было интересно следующее.Я знаю, что nodejs является параллельным, но не многопроцессорным.Если у меня есть обратный вызов, который должен быть выполнен во время выполнения другого кода, он просто приостанавливает выполнение другого кода для обратного вызова?

Учитывая следующий код:

function mycallback(data) {
    // some code
}

function_which_takes_a_callback(mycallback);

for (let i = 0; i < 9999999999; i++) {
    // do something else
}

Если обратный вызоввозвращается, пока цикл for все еще работает, он просто останавливает выполнение цикла и код внутри него для выполнения функции mycallback(), а затем продолжает цикл?Или это завершает цикл?Или еще что-то еще?

И способ, которым nodejs обрабатывает это, отличается от других одновременно работающих, но не многопроцессорных языков (не знаю, какие другие языки, но я предполагаю, что есть другие)?

Ответы [ 2 ]

0 голосов
/ 11 июня 2018
for (let i = 0; i < 9999999999; i++) {
    // some blocking stuff
    // some non-blocking stuff
}

при блокировании , это означает синхронное выполнение кода, которое выполняется системой и не может быть прервано.Рассмотрите возможность изменения размера изображения там или это может быть преобразование документа в PDF, которое реализовано так, чтобы происходить синхронно.

по неблокирующим , это означает код, который выполняет некоторую часть и может ожидать какое-то событие в будущем или некоторый ввод-вывод (запись на диск?, Пользовательский ввод (get) или network (xhr?)), когда такие вызовы выполняются, они запускают свой частичный код и регистрируют себя в очереди, откуда они могут возобновить работу после завершения ожидающей обработки.

Теперь, что произойдет, если будет выполнен следующий код (добавлены номера строк для справки):

1. function mycallback(data) {
2.     // some code
3. }

4. function_which_takes_a_callback(mycallback);

5. for (let i = 0; i < 999; i++) {
6.         // some blocking stuff(for example 1s)
7.         // some non-blocking stuff
8. }

из строки 1-3, зарегистрирована функция mycallback.
вВ строке 4 выполняется function_which_takes_a_callback, и передается mycallback, он выполняет некоторую работу и может вызывать mycallback после выполнения в строке 5-8, 999 раз поток блокируется как минимум 999 раз, пока не будет выполнен mycallback.

Только после того, как этот код будет выполнен с его выполнением, он освободит стек, вызывая цикл обработки событий из очереди событий, которая может быть обработана.

Попробуйте это:

function syncCode() {
    var fromTime = Date.now();
    var toTime = Date.now() + 1000;
    while (fromTime < toTime) {
        fromTime = Date.now();
    }
}
function asyncCode() {
    console.log(new Date(), "Invoked asyncCode");
    setTimeout(() => {
        console.log(new Date(), "async code should have come 1s after Start");
    }, 1000);
}
console.log(new Date(), "Start");
asyncCode();

console.log("Sync code repeatedly for 10s");
for(var i = 0; i < 10; i++) {
    syncCode();
    setTimeout(() => {
        console.log(new Date(), "sync code should be coming after async code callback");
    }, 1000)
}
console.log(new Date(), "End");
0 голосов
/ 11 июня 2018

Если обратный вызов возвращается во время работы цикла for, просто ли он останавливает выполнение цикла и код внутри него для выполнения функции mycallback(), а затем продолжает цикл?

Нет, цикл заканчивается первым, и в какой-то момент позже (или никогда) обратный вызов будет запущен.Синхронный код никогда не прерывается в JS другим кодом JS (хотя он может быть прерван ОС).Переключение внутреннего контекста (т. Е. Переход к обратному вызову) может происходить только в том случае, если в данный момент не выполняется синхронный код.

И способ, которым nodejs обрабатывает это, отличается от других одновременных, но не многопроцессорных процессов.языки (не знаю, какие другие языки, но я предполагаю, что есть другие)?

Проще говоря: другие языки, которые могут порождать потоки, могут запускать несколько синхронных кодов одновременно.Языки, которые не могут создавать потоки, не могут этого сделать.Обычно любой код, который вы запускаете (независимо от того, какой язык вы используете), может быть (и часто) прерывается операционной системой.ОС не позволит вам занять 100% процессорного времени для себя, нет, сэр.Но однопоточные виртуальные машины (например, JS) не способны воспользоваться этим.Как только ОС возвращает управление JS, оно возобновляет работу с того места, где остановилось.Это простое следствие того, что JS является однопоточным (что не на 100% верно, но для простоты я предполагаю, что JS однопоточное).

Другими словами, с точки зрения разработчика, синхронный код JSне может быть прервано никаким внутренним событием.Я также призываю вас проверить это.Например, запланируйте setTimeout и сделайте время проверки цикла занятости:

function busy(timeout) {
    var n = Date.now();
    var end = n + timeout;
    while (n < end)
        n = Date.now();
}
setTimeout(function() { console.log('test'); }, 1000);
busy(3000);

и обратите внимание, что консоль печатает test через 3 с, а не 1 с, как запланировано.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...