Подтвердить что ты не робот

Поскольку JavaScript является однопоточным, как веб-рабочие в HTML5 выполняют многопоточность?

Я читал о веб-работниках в HTML5, но я знаю, что JavaScript является однопоточным.

Мой вопрос:

Как работают веб-сотрудники, выполняющие многопоточную работу? или как они имитируют это, если это не верно многопоточное? Мне кажется неясным здесь.

4b9b3361

Ответ 1

Как уже отмечалось в нескольких комментариях, Workers действительно многопоточны.

Некоторые моменты, которые могут помочь прояснить ваше мышление:

  • JavaScript - это язык, он не определяет модель потоковой передачи, это не обязательно однопоточное
  • Большинство браузеров исторически были однопоточными (хотя это быстро меняется: IE, Chrome, Firefox), и большинство реализаций JavaScript встречаются в браузерах.
  • Работники Web не являются частью JavaScript, это функция браузера, к которой можно получить доступ через JavaScript.

Ответ 2

Вы создаете файл .js как "рабочий", и он запускает процессы в отдельном потоке. Вы можете передавать данные JSON между ними и "основной" нитью. Однако у рабочих нет доступа к некоторым вещам, таким как DOM.

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

Ответ 3

Немного поздно, но я просто задал себе тот же вопрос, и я придумал следующий ответ:
Javascript в браузерах всегда однопоточный, а одновременный доступ к переменным, как правило, не является проблемой; , за исключением веб-мастеров, которые фактически выполняются в отдельных потоках , а параллельный доступ к переменным должен быть рассмотрен несколько явно..

Я не ниндзя JavaScript, но я тоже знал, что JavaScript в браузере предоставляется как один процесс с резьбой.
Простой факт, который поддерживает это предположение, заключается в том, что при программировании в JavaScript вы не должны заботиться о параллельном доступе к общим переменным. Каждый разработчик, даже не думая о проблеме, пишет код так, как будто каждый доступ к переменной согласован. Другими словами, вам не нужно беспокоиться о так называемой модели памяти.

На самом деле нет необходимости смотреть на WebWorkers, чтобы задействовать параллельную обработку в JavaScript. Подумайте о (асинхронном) запросе AJAX. И подумайте, как бы вы небрежно обращались с одновременным доступом к переменным:

var counter = 0;

function asyncAddCounter() {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4) {
      counter++;
    }
  };
  xhttp.open("GET", "/a/remote/resource", true);
  xhttp.send();
}

asyncAddCounter();
counter++;

Каково значение counter в конце процесса? Это 2. Не имеет значения, что он читается и записывается "одновременно", он никогда не приведет к 1. Это означает, что доступ к counter всегда согласован. Если два потока, которые действительно обращаются к значению одновременно, оба они могут начать с чтения 0 и оба пишут 1 в конце.

В браузерах запрос ajax может порождать новый поток для его фактической выборки данных, но его внутренняя работа выходит за рамки JavaScript API (что браузер позволяет вам контролировать с точки зрения инструкций JavaScript). Что касается разработчика, результат запроса newtwork обрабатывается основным потоком.

Это достигается с помощью циклов событий, а не многопоточности. Это справедливо для нескольких браузеров и, очевидно, для Node.js. Ниже приведены некоторые ссылки, в некоторых случаях немного устаревшие, но я предполагаю, что основная идея все еще сохраняется в наши дни.

Этот факт является причиной того, что JavaScript называется Event-driven, но не многопоточным.

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

  • вы передаете данные веб-рабочему (что означает, что новый поток читает данные) с помощью структурированного клона: Структурированный алгоритм клонирования - веб-API | MDN. По существу, нет "общей" переменной, вместо этого новый поток получает новую копию объекта.
  • вы передаете данные веб-работнику, передав право собственности на значение: Transferable - веб-API | MDN. Это означает, что только один поток может прочитать его значение в любое время.
  • Что касается результатов, возвращаемых веб-рабочими (как они "пишут" ), основной поток получает доступ к результатам, когда будет предложено сделать это (например, с инструкцией thisWorker.onmessage = function(e) {console.log('Message ' + e.data + ' received from worker');}). Должно быть, это должно быть с помощью обычной Event Loop.
  • основной поток и веб-рабочий обращаются к по-настоящему разделяемой памяти SharedArrayBuffer, с которой безопасно доступны потоки, используя функции Atomic. Я обнаружил, что это ясно показано в этой статье: JavaScript: от рабочих до общей памяти
  • note: веб-работники не могут получить доступ к DOM, который по-настоящему доступен!

Ответ 4

Браузер запускает поток с помощью javascript, который вы хотите выполнить. Итак, это настоящая нить с этой работой веб-мастеров, ваш js больше не однопоточный.