Чому JavaScript не підтримує багатопотоковість?


269

Це навмисне дизайнерське рішення чи проблема з нашими браузерами, які сьогодні є виправленими у наступних версіях?


3
Дивіться також відповіді на питання JavaScript та теми для інформації про веб-працівників / робочі теми.
Сем Хаслер

115
Привіт, товариш Googler. Ви можете помітити, що тут все здається досить застарілим (зауважте, це питання було задано більше 5 років тому.) Оскільки його задали, веб-браузери отримали деякі можливості, які, наскільки я можу сказати, є більш-менш багатопотоковими. Погляньте на веб-працівників: msdn.microsoft.com/en-us/hh549259.aspx
ArtOfWarfare

2
Multithread.js обертає веб-робітників і дозволяє легко виконувати багатопотокові роботи в JS Працює у всіх нових браузерах, включаючи iOS Safari. :)
kwh

1
Можливий дублікат JavaScript та теми
Метт

Відповіді:


194

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

Однак ви можете використовувати, як було запропоновано, setTimeoutщоб дозволити якесь планування та "фальшиву" паралельність. Це призводить до того, що браузер відновить контроль над потоком візуалізації та запустить код JavaScript, наданий setTimeoutпісля заданої кількості мілісекунд. Це дуже корисно, якщо ви хочете дозволити оглядовому огляду (побаченому) оновитись під час виконання операцій над ним. Якщо просто переглядати координати, наприклад, координати та відповідно оновлювати елемент, ви просто зможете побачити початкову та кінцеву позиції, і нічого між ними.

Ми використовуємо бібліотеку абстракцій у JavaScript, яка дозволяє нам створювати процеси та потоки, якими керує той самий інтерпретатор JavaScript. Це дозволяє нам виконувати дії таким чином:

  • Процес A, Нитка 1
  • Процес A, Нитка 2
  • Процес B, Нитка 1
  • Процес А, Нитка 3
  • Процес А, Нитка 4
  • Процес B, Нитка 2
  • Призупинення процесу A
  • Процес В, Нитка 3
  • Процес B, Нитка 4
  • Процес B, Нитка 5
  • Запустіть процес A
  • Процес А, Нитка 5

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

Для майбутнього JavaScript перевірте це: https://developer.mozilla.org/presentations/xtech2006/javascript/


73
Я думаю, що ніколи не реалізоване це занадто вузьке бачення. Я гарантую, що з часом веб-додатки зможуть бути справді багатопоточними (це лише логічно, оскільки веб-додатки стають більш домінуючими, а апаратне забезпечення стає більш паралельним), і як я це бачу, оскільки JavaScript є фактичною мовою веб-розробки, це врешті-решт доведеться підтримувати багатопотоковість або бути замінені чимось, що це робить.
devios1

6
Ніколи, мабуть, не занадто сміливий вислів :), але я все-таки вважаю, що переваги справжнього багатопотокового javascript неможливо здійснити в осяжному майбутньому;)
Kamiel Wanrooij

5
Хоча я б заперечував, що веб-працівники мають більше паралельних процесових моделей, ніж потокових. Працівники Інтернету використовують передачу повідомлень як засіб комунікації, що є елегантним рішенням «звичайних» питань паралельної конкуренції у багатопотокових програмах. Я не впевнений, чи можуть вони реально працювати над тими ж об’єктами, що й основна сторінка. Наскільки я знаю, вони не можуть отримати доступ до DOM. Більшість це семантика, хоча працівники Інтернету виглядають перспективними для всіх намірів та цілей.
Kamiel Wanrooij

труднощі є набагато більшими, ніж додаткові можливості. Я не впевнений, якщо ви думаєте про всі додаткові можливості. Я особливо думаю про випадки, коли webgl використовується як в іграх чи графічних візуалізаціях. Наприклад, розгляньте нову тривимірну версію Карт Google. У містах з багатьма 3D-моделями моєму ПК потрібно ~ 2 хв, щоб завантажити все, коли потрібно зробити багато будинків. Під певними кутами ні моя відеокарта, ні моя мережа не працюють на потужність. Але 1 з 8 процесорів на 100%. Багатопоточне читання також викликає велике занепокоєння з точки зору fps, як показує цей приклад: youtube.com/watch?v=sJ2p982cZFc
Scindix,

25

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

Безпека ниток даних гарантована, оскільки всі дані, що передаються працівнику / від них, серіалізуються / копіюються.

Для отримання додаткової інформації читайте:

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

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


8
Але хіба це не більше багатопроцесорний підхід, а не багатопотоковий? Відомо, що нитки працюють в межах однієї купи.
beefeather

1
@beefeather, це правда. Це скоріше процесний підхід.
Ніл

23

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

Звичайно, зараз у нас це є. Але браузерам знадобиться трохи наздогнати - більшість з них розроблені навколо однопотокової моделі, і змінити це непросто. Google Gears виконує багато можливих проблем, вимагаючи, щоб фонове виконання було ізольованим - не змінюючи DOM (оскільки це не є безпечним для потоків), немає доступу до об'єктів, створених головним потоком (ditto). Незважаючи на обмеження, це, швидше за все, буде найбільш практичним дизайном на найближче майбутнє, як тому, що спрощує дизайн браузера, так і тому, що це зменшує ризик дозволити недосвідченим кодерам JS заплутатися з нитками ...

@marcio :

Чому це причина не застосовувати багатопотоковість у Javascript? Програмісти можуть робити все, що завгодно, за допомогою інструментів, які вони мають.

Тож давайте не дамо їм інструментів, які так легко не зловживати, що кожен інший відкритий веб-сайт закінчується збоєм мого браузера. Наївна реалізація цього привела б вас прямо на територію, яка викликала в MS стільки головних болів під час розробки IE7: автори додатків грали швидко і вільно з нарізною моделлю, в результаті чого приховані помилки, які стали очевидними при зміні життєвих циклів об'єктів на первинному потоці . БАД. Якщо ви пишете багатопотокові додатки ActiveX для IE, я думаю, що це стосується території; не означає, що потрібно йти далі від цього.


6
"це знижує ризик, що пов'язаний з тим,> що дозволяє недосвідченим кодерам JS> возитися з потоками". Чому це причина не застосовувати багатопотоковість у Javascript? Програмісти можуть робити все, що завгодно, за допомогою інструментів, які вони мають. Якщо це добре чи погано, це їхня проблема. З моделлю процесу Google Chrome він не може впливати навіть на інші програми. :)
Marcio Aguiar

3
@ Shog9 - "Давайте не надавати [програмістам] інструменти, які так легко зловживати, що кожен інший веб-сайт, який я відкриваю, закінчується збоєм мого браузера." - Що? За цією ж логікою жодна мова не повинна мати багатопотоковість, бо якби вони запропонували, що будь-яка інша програма, яку ви намагалися відкрити, зазнала краху. За винятком цього не працює. Тематика існує на більшості мов, і більшість початківців програмістів не торкаються її, і більшість тих, хто не виробляє її, і ті програми, які ніколи не стають популярними або широко використовуються.
ArtOfWarfare

11

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

Просто попросіть свою функцію трохи попрацювати, а потім зателефонуйте на зразок:

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

І будь-які інші речі, які потрібно робити (наприклад, оновлення інтерфейсу користувача, анімовані зображення тощо), трапляться, коли вони отримають можливість.


Більшість випадків я хотів би використовувати loopвсередині, setTimeoutале, мабуть, це не працює. Ви робили щось подібне чи у вас хакер? прикладом може бути масив з 1000 елемента, я очікую використання двох для циклів всередині двох setTimeoutвикликів, таким чином, що перший цикл проходить через і друкує елемент 0..499, другий цикл проходить через і елемент друку 500..999.
Бенджамінц

Зазвичай техніка - зберегти стан і продовжити. Наприклад, скажімо, що ви хочете надрукувати від 0 до 1000, ви можете надрукувати від 0 до 499, а потім виконати трюк setTimeout з аргументом 500. Код всередині міг би взяти аргумент (500) і запустити цикл звідти.
Eyal

8

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

Відповідь на перше запитання полягає в тому, що JavaScript в браузері призначений для роботи в пісочниці та машинно / не залежно від ОС, додавання підтримки для багатопотокових передач ускладнить мову та прив'язує мову занадто тісно до ОС.


6

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

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

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

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

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


4

Як вже говорив matt b, питання не дуже зрозуміле. Якщо припустити, що ви запитуєте про підтримку багатопотокової мови мовою: адже вона не потрібна для 99,999% застосованих у браузері додатків. Якщо вам це справді потрібно, є обхідні шляхи (наприклад, за допомогою window.setTimeout).

Взагалі, багатопотоковість - це дуже, дуже, дуже, дуже, дуже, дуже важко (я сказав, що це важко?) Отримати правильне рішення, якщо ви не встановите додаткові обмеження (наприклад, використовуючи лише незмінні дані).


3

Intel проводила кілька досліджень з відкритим кодом з багатопотокової роботи в Javascript, її недавно було показано на GDC 2012. Ось посилання на відео . Дослідницька група використовувала OpenCL, який в основному зосереджується на наборах чіпів Intel та ОС Windows. Проект має кодову назву RiverTrail і код доступний на GitHub

Ще кілька корисних посилань:

Побудова обчислювальної дороги для веб-додатків


2

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


1

Це реалізація, яка не підтримує багатопотоковість. В даний час Google Gears пропонує спосіб використовувати певну форму одночасності, виконуючи зовнішні процеси, але це стосується цього.

Новий браузер Google повинен випустити сьогодні (Google Chrome) паралельно виконує деякий код, відокремлюючи його.

Основна мова, звичайно, може мати таку ж підтримку, як, скажімо, Java, але підтримка чогось на зразок одночасності Ерланга ніде не знаходиться біля горизонту.


1

Javascript - це однопоточна мова. Це означає, що він має один стек викликів та одну купу пам'яті. Як очікувалося, він виконує код для того, щоб завершити виконання фрагмента коду, перш ніж перейти до наступного. Це синхронно, але часом може бути шкідливим. Наприклад, якщо функція потребує деякого часу, щоб виконати або доводиться щось чекати, вона тим часом заморожує все.


0

Наскільки я почув, Google Chrome матиме багатопотоковий javascript, тому це проблема "поточної реалізації".


0

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


-1

Однак ви можете скористатися функцією 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;
    }
}

-2

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

Основна відмінність веб-роботників від стандартного багатопотокового середовища полягає в тому, що ресурси пам’яті не поділяються на основний потік, посилання на об’єкт не видно з одного потоку в інший. Нитки спілкуються за допомогою обміну повідомленнями, тому можливо реалізувати алгоритм виклику синхронізації та паралельного виклику, керуючись подією дизайнерської схеми.

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


5
Обмін пам’яттю - це точне визначення теми, що протистоїть окремому процесу (наприклад, fork () vs exec ()). Нитки можуть спільно використовувати об'єкти, процеси повинні використовувати IPC. Веб-працівники не є багатопоточними.
felixfbecker
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.