Почему JavaScript не поддерживает многопоточность?

Это преднамеренное дизайнерское решение или проблема современных браузеров, которая будет исправлена ​​в следующих версиях?


person Community    schedule 02.09.2008    source источник
comment
См. Также ответы на вопрос JavaScript и потоки для получения информации о веб-воркерах / рабочих потоках.   -  person Sam Hasler    schedule 02.09.2008
comment
Привет, товарищ Google. Вы могли заметить, что все здесь выглядит довольно устаревшим (обратите внимание, что этот вопрос был задан более 5 лет назад). С тех пор, как он был задан, веб-браузеры получили некоторые возможности, которые, насколько я могу судить, являются более или менее многопоточными. Взгляните на веб-воркеров: msdn.microsoft.com/en-us/hh549259.aspx   -  person ArtOfWarfare    schedule 07.11.2013
comment
Multithread.js обертывает веб-воркеров и позволяет легко выполнять многопоточность в JS. Работает во всех новых браузерах, включая iOS Safari. :)   -  person kwh    schedule 08.03.2014
comment
Возможный дубликат JavaScript и потоков   -  person Matt    schedule 23.05.2018
comment
вы можете использовать (серверный работник). Сервисный воркер - это скрипт, который ваш браузер запускает в фоновом режиме, отдельно от веб-страницы, открывая доступ к функциям, которым не нужна веб-страница или взаимодействие с пользователем.   -  person Omar bakhsh Available to work    schedule 19.07.2020


Ответы (15)


JavaScript не поддерживает многопоточность, поскольку интерпретатор JavaScript в браузере является однопоточным (AFAIK). Даже Google Chrome не позволяет запускать JavaScript одной веб-страницы одновременно, потому что это вызовет серьезные проблемы параллелизма на существующих веб-страницах. Все, что делает Chrome, - это разделяет несколько компонентов (разные вкладки, плагины и т. Д.) На отдельные процессы, но я не могу представить себе одну страницу, имеющую более одного потока JavaScript.

Однако вы можете использовать, как было предложено, setTimeout, чтобы разрешить какое-то планирование и «фальшивый» параллелизм. Это заставляет браузер восстановить контроль над потоком рендеринга и запустить код JavaScript, предоставленный setTimeout, через заданное количество миллисекунд. Это очень полезно, если вы хотите, чтобы область просмотра (то, что вы видите) обновлялась во время выполнения операций с ней. Просто прокручиваю, например. координаты и соответствующее обновление элемента просто позволит вам увидеть начальную и конечную позиции, и ничего между ними.

Мы используем библиотеку абстракций в JavaScript, которая позволяет нам создавать процессы и потоки, которыми управляет один и тот же интерпретатор JavaScript. Это позволяет нам запускать действия следующим образом:

  • Процесс A, поток 1
  • Процесс A, поток 2
  • Процесс B, поток 1
  • Процесс A, поток 3
  • Процесс A, поток 4
  • Процесс B, поток 2
  • Приостановить процесс A
  • Процесс B, поток 3
  • Процесс B, поток 4
  • Процесс B, поток 5
  • Начать процесс A
  • Процесс A, поток 5

Это допускает некоторую форму планирования и имитирует параллелизм, запуск и остановку потоков и т. Д., Но это не будет истинной многопоточностью. Я не думаю, что это когда-либо будет реализовано в самом языке, поскольку настоящая многопоточность полезна только в том случае, если браузер может запускать одностраничный многопоточный (или даже более одного ядра), а трудности там намного больше. чем дополнительные возможности.

Что касается будущего JavaScript, проверьте это: https://web.archive.org/web/20170920070053/https://developer.mozilla.org/presentations/xtech2006/javascript/

person Kamiel Wanrooij    schedule 02.09.2008
comment
Я думаю, что никогда не реализовано - это слишком узкое видение. Я гарантирую, что веб-приложения в конечном итоге смогут быть по-настоящему многопоточными (это логично, поскольку веб-приложения становятся все более доминирующими, а оборудование - более параллельным), и, как я это вижу, поскольку JavaScript де-факто является языком веб-разработки, он в конечном итоге придется поддерживать многопоточность или заменяться чем-то, что поддерживает. - person devios1; 02.06.2011
comment
«Никогда», наверное, слишком смелое заявление :), но я все же считаю, что преимущества настоящего многопоточного javascript в обозримом будущем неосуществимы;) - person Kamiel Wanrooij; 10.06.2011
comment
Хотя я бы сказал, что веб-воркеры более параллельны через модель процесса, чем модель потока. Веб-воркеры используют передачу сообщений в качестве средства связи, что является элегантным решением «обычных» проблем параллелизма в многопоточных приложениях. Я не уверен, могут ли они одновременно работать с теми же объектами, что и главная страница. Насколько мне известно, они не могут получить доступ к DOM. По большей части это семантика, веб-воркеры выглядят многообещающе во всех смыслах. - person Kamiel Wanrooij; 29.06.2012
comment
трудностей намного больше, чем дополнительных возможностей Я не уверен, что вы думаете обо всех дополнительных возможностях. Я особенно думаю о случаях, когда webgl используется, например, в играх или графических визуализациях. Например. рассмотрим новую трехмерную версию Google Maps. В городах с большим количеством 3D-моделей моему компьютеру требуется ~ 2 минуты, чтобы загрузить все, когда нужно отрендерить много домов. При определенных углах ни моя видеокарта, ни моя сеть не работают на полную мощность. Но 1 из 8 процессоров на 100%. Многопоточность также вызывает серьезную озабоченность с точки зрения частоты кадров в секунду, как показывает этот пример: youtube.com/watch?v=sJ2p982cZFc - person Scindix; 11.01.2017

Многопоточность JavaScript (с некоторыми ограничениями) здесь. Google внедрил воркеры для Gears, и они включены в HTML5. Большинство браузеров уже добавили поддержку этой функции.

Потоковая безопасность данных гарантируется, потому что все данные, передаваемые работнику / от работника, сериализуются / копируются.

Для получения дополнительной информации прочтите:

http://www.whatwg.org/specs/web-workers/current-work/

http://ejohn.org/blog/web-workers/

person Community    schedule 30.04.2010
comment
Но разве это не многопроцессорный подход, а не многопоточность? Известно, что потоки работают в одной куче. - person beefeather; 18.08.2016
comment
@beefeather, это правда. Это больше процессный подход. - person Neil; 09.09.2016
comment
У WebWorkers нет разделяемой памяти. Для общения друг с другом они отправляют сообщения. Сообщения - это копии памяти. Это медленнее, чем общая память. - person neoexpert; 05.07.2020

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

Конечно, теперь оно у нас есть. Но браузерам потребуется немного времени, чтобы наверстать упущенное - большинство из них были разработаны на основе однопоточной модели, и изменить ее непросто. Google Gears устраняет множество потенциальных проблем, требуя изолированного фонового выполнения - без изменения DOM (поскольку он не является поточно-ориентированным), без доступа к объектам, созданным основным потоком (то же самое). Хотя это и носит ограничительный характер, это, вероятно, будет наиболее практичным дизайном в ближайшем будущем, потому что он упрощает дизайн браузера и потому, что он снижает риск, связанный с тем, что неопытным JS-кодерам разрешается возиться с потоками ...

@marcio:

Почему это причина не реализовывать многопоточность в Javascript? Программисты могут делать все, что захотят, с помощью имеющихся у них инструментов.

Так что давайте не будем давать им инструменты, которыми так легко злоупотребить, что любой другой веб-сайт, который я открываю, приводит к сбою моего браузера. Наивная реализация этого приведет вас прямо на территорию, которая вызвала у MS столько головной боли во время разработки IE7: авторы надстроек играли быстро и свободно с потоковой моделью, что приводило к скрытым ошибкам, которые становились очевидными, когда жизненные циклы объектов изменялись в основном потоке. . ПЛОХОЙ. Если вы пишете многопоточные надстройки ActiveX для IE, я полагаю, что это связано с территорией; не означает, что нужно идти дальше этого.

person Shog9    schedule 02.09.2008
comment
это снижает риск, связанный ›позволяя неопытным кодировщикам JS› возиться с потоками. Почему это причина не реализовывать многопоточность в Javascript? Программисты могут делать все, что захотят, с помощью имеющихся у них инструментов. Хорошо это или плохо, это их проблемы. С моделью процесса Google Chrome он даже не может повлиять на другие приложения. :) - person Marcio Aguiar; 02.09.2008
comment
@ Shog9 - Давайте не будем давать [программистам] инструменты, которыми так легко злоупотреблять, что любой другой веб-сайт, который я открываю, приводит к сбою моего браузера. - Какие? По той же логике ни один язык не должен иметь многопоточность, потому что, если они предложат это, любая другая программа, которую вы пытаетесь открыть, выйдет из строя. Только вот так не работает. Многопоточность существует на большинстве языков, и большинство начинающих программистов не трогают ее, а большинство из тех, кто ее не использует, не запускают в производство, а также те приложения, которые никогда не становятся популярными или широко используются. - person ArtOfWarfare; 07.11.2013

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

Просто дайте вашей функции немного поработать, а затем вызовите что-то вроде:

setTimeout(function () {
    ... do the rest of the work...
}, 0);

И любые другие вещи, которые необходимо сделать (например, обновления пользовательского интерфейса, анимированные изображения и т. Д.), Произойдут, когда у них появится такая возможность.

person pkaeding    schedule 02.09.2008
comment
В большинстве случаев я бы хотел использовать loop внутри setTimeout, но, видимо, это не работает. Ты делал что-нибудь подобное или у тебя есть хак? пример будет для массива из 1000 элементов, я ожидаю использовать два цикла for внутри двух вызовов setTimeout, так что первый проходит и печатает элемент 0..499, второй проходит и печатает элемент 500..999. - person benjaminz; 01.11.2016
comment
Обычно техника заключается в том, чтобы сохранить состояние и продолжить. Например, если вы хотите вывести от 0 до 1000, вы можете вывести от 0 до 499, а затем выполнить трюк с setTimeout с аргументом 500. Код внутри будет знать, что нужно принять аргумент (500) и начать цикл оттуда. - person Eyal; 01.02.2017

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

Ответ на первый вопрос заключается в том, что JavaScript в браузере предназначен для запуска в изолированной программной среде и независимо от машины / ОС, добавление поддержки многопоточности усложнит язык и слишком тесно связывает язык с ОС.

person matt b    schedule 02.09.2008

Node.js 10.5+ поддерживает рабочие потоки как экспериментальную функцию (вы можете использовать ее с включенным флагом --experimental-worker): https://nodejs.org/api/worker_threads.html

Итак, правило такое:

  • если вам нужно выполнить операции с привязкой к вводу-выводу, используйте внутренний механизм (также известный как обратный вызов / обещание / async-await)
  • если вам нужно выполнить операции с привязкой к ЦП, используйте рабочие потоки.

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

В противном случае, если вам нужно выполнить большую нагрузку на ЦП с помощью анонимной функции, вы можете использовать https://github.com/wilk/microjob, крошечная библиотека, построенная на рабочих потоках.

person Community    schedule 06.09.2018

Как сказал Мэтт Би, вопрос не очень ясен. Предполагая, что вы спрашиваете о поддержке многопоточности на языке: потому что это не требуется для 99,999% приложений, работающих в настоящее время в браузере. Если вам это действительно нужно, есть обходные пути (например, с помощью window.setTimeout).

В общем, многопоточность очень, очень, очень, очень, очень, очень сложно (я сказал, что это сложно?), Если вы не наложите дополнительные ограничения (например, использование только неизменяемых данных).

person Grey Panther    schedule 02.09.2008

Intel проводила исследования с открытым исходным кодом по многопоточности в Javascript, недавно они были продемонстрированы на GDC 2012. Вот ссылка на видео. Исследовательская группа использовала OpenCL, который в первую очередь ориентирован на наборы микросхем Intel и ОС Windows. Проект носит кодовое название RiverTrail, и его код доступен на GitHub.

Еще несколько полезных ссылок:

Создание вычислительной магистрали для веб-приложений

person Community    schedule 01.04.2012

В настоящее время некоторые браузеры поддерживают многопоточность. Итак, если вам это нужно, вы можете использовать определенные библиотеки. Например, просмотрите следующие материалы:

person Community    schedule 07.12.2015

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

person Community    schedule 21.01.2020

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

Новый браузер, который Google должен выпустить сегодня (Google Chrome), выполняет некоторый код параллельно, разделяя его в процессе.

Базовый язык, конечно, может иметь ту же поддержку, что, скажем, Java, но поддержка чего-то вроде параллелизма в Erlang далеко не за горами.

person Greg Roberts    schedule 02.09.2008

Насколько я слышал, в Google Chrome будет многопоточный javascript, так что это проблема «текущих реализаций».

person BlaM    schedule 02.09.2008

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

person Community    schedule 08.03.2010

Однако вы можете использовать функцию eval, чтобы довести параллелизм до некоторой степени.

/* content of the threads to be run */
var threads = [
        [
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');",
            "document.write('Foo <br/>');"
        ],
        [
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');",
            "document.write('Bar <br/>');"
        ]
    ];

window.onload = function() {
    var lines = 0, quantum = 3, max = 0;

    /* get the longer thread length */
    for(var i=0; i<threads.length; i++) {
        if(max < threads[i].length) {
            max = threads[i].length;
        }
    }

    /* execute them */
    while(lines < max) {
        for(var i=0; i<threads.length; i++) {
            for(var j = lines; j < threads[i].length && j < (lines + quantum); j++) {
                eval(threads[i][j]);
            }
        }
        lines += quantum;
    }
}
person Community    schedule 11.02.2017

Очевидно, что многопоточность с javascript возможна с использованием веб-работников, созданных с помощью HTML5.

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

Существует множество фреймворков, позволяющих структурировать программирование между потоками, среди них OODK-JS, фреймворк OOP js, поддерживающий параллельное программирование https://github.com/GOMServices/oodk-js-oop-for-js

person Community    schedule 11.09.2016
comment
Совместное использование памяти - это точное определение потока в отличие от отдельного процесса (например, fork () vs exec ()). Потоки могут совместно использовать объекты, процессы должны использовать IPC. Веб-воркеры не являются многопоточными. - person felixfbecker; 14.11.2016