Я читал о веб-воркерах в HTML5, но я знаю, что JavaScript однопоточный.
Мой вопрос:
Как тогда веб-воркеры справляются с многопоточной работой? или как они имитируют его, если он не является многопоточным? Мне здесь не ясно.
Я читал о веб-воркерах в HTML5, но я знаю, что JavaScript однопоточный.
Мой вопрос:
Как тогда веб-воркеры справляются с многопоточной работой? или как они имитируют его, если он не является многопоточным? Мне здесь не ясно.
Как уже отмечалось в нескольких комментариях, Workers действительно являются многопоточными.
Некоторые моменты, которые могут помочь прояснить ваше мышление:
Немного поздно, но я только что задал себе тот же вопрос и пришел к следующему ответу:
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, которые дают разработчику контроль над многопоточным процессом.
Таким образом, они предоставляют явные способы обработки параллельного доступа к общей памяти (чтение и запись значений в разных потоках). ), и делается это, в том числе, следующими способами:
thisWorker.onmessage = function(e) {console.log('Message ' + e.data + ' received from worker');}
). Я должен предположить, что это должно быть с помощью обычного цикла событий.SharedArrayBuffer
, доступ к которой осуществляется потокобезопасно с помощью функций Atomic
. Я нашел это ясно изложенным в этой статье: JavaScript: От рабочих операций к общей памятиВы создаете файл .js как «рабочий», и он запускает процессы в отдельном потоке. Вы можете передавать данные JSON туда и обратно между ним и «основным» потоком. Однако рабочие не имеют доступа к некоторым вещам, таким как DOM.
Итак, если, скажем, вы хотите решить сложные математические задачи, вы можете позволить пользователю вводить данные в браузер, передавать эти переменные рабочему процессу, позволяя ему выполнять вычисления в фоновом режиме, в то время как в основном потоке вы позволяете пользователю делать это. другие вещи, или показать индикатор выполнения или что-то еще, а затем, когда рабочий закончит работу, он передаст ответ обратно, и вы распечатаете его на странице. Вы даже можете выполнять несколько задач асинхронно и возвращать ответы не по порядку по мере их завершения. Довольно аккуратно!
Браузер запускает поток с javascript, который вы хотите выполнить. Так что это настоящий поток, с этим веб-работником, ваш js больше не является однопоточным.
На самом деле основная путаница, я думаю, заключается в том, что люди находят умные способы делать что-то одновременно. Если подумать, JavaScript явно не является многопоточным, и все же у нас есть способы делать что-то параллельно, так что же происходит?
Задав правильный вопрос, вы получите ответ здесь. Кто отвечает за темы? Выше есть один ответ, в котором говорится, что JS — это просто язык, а не модель потоков. Совершенно верно! JavaScript здесь ни при чем. Ответственность ложится на V8. Перейдите по этой ссылке для получения дополнительной информации -> https://v8.dev/ Таким образом, V8 позволяет использовать один поток для каждого JS. Контекст, а это значит, что как ни старайся, создать новый тред просто невозможно. Но люди порождают так называемых рабочих, и мы запутались. Чтобы на это ответить, я прошу вас о следующем. Возможно ли запустить 2 V8, и оба они будут интерпретировать некоторый код JS? Именно решение нашей проблемы. Рабочие взаимодействуют с сообщениями, потому что их контекст отличается. Это другие вещи, которые ничего не знают о нашем контексте, поэтому им нужна некоторая информация, которая приходит в форме сообщения.