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

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

Мой вопрос:

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


person James Drinkard    schedule 14.03.2012    source источник
comment
Рабочие действительно запускаются в отдельных потоках.   -  person kirilloid    schedule 14.03.2012
comment
Рабочие потоки по определению являются отдельными потоками.   -  person Ates Goral    schedule 14.03.2012
comment
Я не обижаюсь, я здесь, чтобы учиться и помогать. Я понимаю, что не все знаю.   -  person James Drinkard    schedule 14.03.2012


Ответы (5)


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

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

  • JavaScript — это язык, он не определяет поточную модель, он не обязательно однопоточный.
  • Большинство браузеров исторически были однопоточными (хотя это быстро меняется: IE, Chrome, Firefox), и большинство реализаций JavaScript происходят в браузерах.
  • Веб-воркеры не являются частью JavaScript, это функция браузера, доступ к которой можно получить через JavaScript.
person robertc    schedule 14.03.2012
comment
Вот где я упустил различие, это со спецификацией браузера, а не с языком JavaScript. - person James Drinkard; 14.03.2012
comment
@JamesDrinkard Я думаю, что основная проблема в том, что DOM нельзя легко сделать многопоточным , а JavaScript обычно используется для манипулирования DOM. Но DOM — это не JavaScript. - person robertc; 14.03.2012
comment
@JamesDrinkard javascript по-прежнему является однопоточным, даже с веб-работниками. Веб-воркеры не делают javascript многопоточным, как это было раньше, подумайте об этом так: вы, по сути, запускаете еще один однопоточный процесс и взаимодействуете с ним, как вы могли бы это сделать в узле. js например. javascript в браузере однопоточный, а javascript в воркере однопоточный, но они могут общаться друг с другом через тонкий канал. - person TKoL; 15.03.2018
comment
вот как я понял: браузер использует один поток (с кодом javascript) для рендеринга DOM и обработки связанного цикла событий (который также может содержать код javascript для выполнения не-dom вещей, таких как добавление двух чисел), но мы можем использовать worker, через который браузер может делать только не-dom (все еще javascript) код. Затем мы можем синхронизировать данные между ними (вставьте сюда концепции многопоточности). Итак, перефразируя @James Drinkard, браузер обрабатывает DOM в однопоточном javascript; у нас все еще могут быть другие потоки javascript, которые не касаются DOM - person gawkface; 30.10.2018

Немного поздно, но я только что задал себе тот же вопрос и пришел к следующему ответу:
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 в конце.

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

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

Этот факт является причиной того, что JavaScript считается управляемым событиями, но не многопоточным.< br> Обратите внимание, что таким образом JavaScript допускает асинхронные идиомы, но не параллельное выполнение кода JavaScript (вне веб-воркеров). Термин асинхронный просто обозначает тот факт, что результат двух инструкций может обрабатываться в зашифрованном порядке.

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

  • вы передаете данные веб-воркеру (что означает, что новый поток читает данные) с помощью структурированного клона: Алгоритм структурированного клонирования — веб-API | МДН. По сути, нет «общей» переменной, вместо этого новому потоку предоставляется свежая копия объекта.
  • вы передаете данные веб-воркеру, передавая право собственности на значение: API | МДН. Это означает, что только один поток может прочитать свое значение в любое время.
  • что касается результатов, возвращаемых веб-воркерами (как они «пишут»), основной поток получает доступ к результатам, когда его об этом просят (например, с помощью инструкции thisWorker.onmessage = function(e) {console.log('Message ' + e.data + ' received from worker');}). Я должен предположить, что это должно быть с помощью обычного цикла событий.
  • основной поток и веб-воркер получают доступ к действительно общей памяти, SharedArrayBuffer, доступ к которой осуществляется потокобезопасно с помощью функций Atomic. Я нашел это ясно изложенным в этой статье: JavaScript: От рабочих операций к общей памяти
  • примечание: вебворкеры не могут получить доступ к DOM, который действительно является общим!
person Antonio    schedule 23.11.2017

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

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

person JKing    schedule 14.03.2012
comment
JSON (обозначение объектов Javascript) хранится в строках, поэтому вы должны сказать, что можете передавать строки. В соответствии с этим вопросом postMessage может отправлять клоны различных объектов: объекты"> stackoverflow.com/questions/13761968/ Согласно статье MDN (в которой не упоминается, что существовали только строки), вы можете передавать определенные объекты (что быстрее, чем копирование): developer.mozilla.org/en-US/docs/Web/API/Worker /postMessage Исходя из этого, должна быть возможность связать Workers вместе в конвейер, используя MessagePorts... - person Chinoto Vokro; 15.11.2016

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

person rapadura    schedule 14.03.2012

На самом деле основная путаница, я думаю, заключается в том, что люди находят умные способы делать что-то одновременно. Если подумать, JavaScript явно не является многопоточным, и все же у нас есть способы делать что-то параллельно, так что же происходит?

Задав правильный вопрос, вы получите ответ здесь. Кто отвечает за темы? Выше есть один ответ, в котором говорится, что JS — это просто язык, а не модель потоков. Совершенно верно! JavaScript здесь ни при чем. Ответственность ложится на V8. Перейдите по этой ссылке для получения дополнительной информации -> https://v8.dev/ Таким образом, V8 позволяет использовать один поток для каждого JS. Контекст, а это значит, что как ни старайся, создать новый тред просто невозможно. Но люди порождают так называемых рабочих, и мы запутались. Чтобы на это ответить, я прошу вас о следующем. Возможно ли запустить 2 V8, и оба они будут интерпретировать некоторый код JS? Именно решение нашей проблемы. Рабочие взаимодействуют с сообщениями, потому что их контекст отличается. Это другие вещи, которые ничего не знают о нашем контексте, поэтому им нужна некоторая информация, которая приходит в форме сообщения.

person Ivailo Manolov    schedule 28.05.2021