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

210

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

  • 3
    См. Также ответы на вопрос JavaScript и Threads для получения информации о веб-работниках / рабочих потоках.
  • 103
    Привет, приятель Гуглер. Вы можете заметить, что здесь все выглядит довольно устаревшим (обратите внимание, что этот вопрос был задан более 5 лет назад). С тех пор, как его спросили, веб-браузеры получили некоторые возможности, которые, насколько я могу судить, являются более или менее многопоточными. Взгляните на веб-работников: msdn.microsoft.com/en-us/hh549259.aspx
Показать ещё 1 комментарий
Теги:
multithreading
browser

17 ответов

156
Лучший ответ

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

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

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

  • Процесс А, Поток 1
  • Процесс А, Поток 2
  • Процесс Б, Поток 1
  • Процесс А, Поток 3
  • Процесс А, Поток 4
  • Процесс Б, Поток 2
  • Пауза Процесс А
  • Процесс B, Поток 3
  • Процесс B, Поток 4
  • Процесс B, Поток 5
  • Начать процесс A
  • Процесс А, Поток 5

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

Для будущего JavaScript, проверьте это: https://developer.mozilla.org/presentations/xtech2006/javascript/

  • 62
    Я думаю, что никогда не реализовано слишком узкое видение. Я гарантирую, что веб-приложения в конечном итоге смогут стать действительно многопоточными (это логично, поскольку веб-приложения становятся все более доминирующими, а оборудование становится более параллельным), и, как я вижу, поскольку JavaScript является де-факто языком веб-разработки, он в конечном итоге придется поддерживать многопоточность или заменить что-то, что делает.
  • 6
    Никогда, пожалуй, не слишком смелое утверждение :), но я все же думаю, что преимущества настоящего многопоточного javascript не осуществимы в обозримом будущем;)
Показать ещё 4 комментария
21

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

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

@marcio:

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

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

  • 4
    «Это снижает риск, связанный с тем, что неопытные JS-кодеры могут> возиться с потоками». Почему это не является причиной реализации многопоточности в Javascript? Программисты могут делать с инструментами все, что хотят. Если это хорошо или плохо, это их проблема. С моделью процесса Google Chrome это не может повлиять даже на другие приложения. :)
  • 3
    @Shog9 Shog9 - «Давайте не будем давать [программистам] инструменты, которыми так легко злоупотреблять, что любой другой веб-сайт, который я открываю, приводит к сбою моего браузера». - Какие? По той же логике, ни у одного языка не должно быть многопоточности, потому что если бы они предложили, чтобы любая другая программа, которую вы пытались открыть, вылетала. За исключением того, что это не работает таким образом. Многопоточность существует в большинстве языков, и большинство начинающих программистов ее не трогают, а также большинство тех, кто ее не использует, и те приложения, которые никогда не становятся популярными или широко используемыми.
19

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

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

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

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

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

  • 6
    Но разве это не многопоточный подход, а не многопоточный? Известно, что потоки работают в одной куче.
  • 1
    @beefeather beefeather, это правда. Это скорее процессный подход.
11

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

Просто выполните свою работу немного, а затем вызовите что-то вроде:

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

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

  • 0
    В большинстве случаев я хотел бы использовать loop внутри setTimeout но, очевидно, это не работает. Вы сделали что-нибудь подобное или у вас есть взлом? Например, для массива из 1000 элементов, я ожидаю использовать два цикла for внутри двух вызовов setTimeout , так что первый цикл проходит и печатает элемент 0..499 , второй цикл и печатает элемент 500..999 .
  • 0
    Обычно техника заключается в том, чтобы сохранить состояние и продолжить. Например, допустим, что вы хотите вывести от 0 до 1000, вы можете вывести от 0 до 499, а затем выполнить трюк setTimeout с аргументом 500. Код внутри будет знать, что взять аргумент (500) и запустить цикл оттуда.
10

Multithread.js обертывает Web Workers и позволяет легко многопоточно обрабатывать JS. Работает во всех новых браузерах, включая iOS Safari.:)

7

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

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

5

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

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

3

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

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

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

2

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

1

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

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

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

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

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

0

вы можете использовать jetworker, обертку на веб-сайте https://github.com/uxitten/jetworker

0

Однако вы можете использовать функцию eval, чтобы принести concurrency В НЕКОТОРЫЕ EXTENT

/* 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;
    }
}
0

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

0

В соответствии с в этой статье уже возможно реализовать потоки JavaScript.

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

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

0

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

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

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

-3

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

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

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

  • 5
    Совместное использование памяти - это точное определение потока, противоположного отдельному процессу (например, fork () против exec ()). Потоки могут совместно использовать объекты, процессы должны использовать IPC. Веб-работники не многопоточность.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню