JavaScriptがマルチスレッドをサポートしないのはなぜですか?


269

それは意図的な設計の決定なのか、それとも今後のバージョンで修正される今日のブラウザーの問題なのか?


3
Webワーカー/ワーカースレッドについては、JavaScriptとスレッドの質問への回答もご覧ください。
サムハスラー

115
こんにちは、Google社員。ここですべてがかなり古くなっているように見えるかもしれません(この質問は5年以上前に尋ねられたことに注意してください)。Webワーカーを
ご覧

2
Multithread.jsは Webワーカーをラップし、JSでの簡単なマルチスレッド化を可能にします。iOS Safariを含むすべての新しいブラウザーで動作します。:)
kwh 2014年

回答:


194

ブラウザのJavaScriptインタプリタはシングルスレッド(AFAIK)であるため、JavaScriptはマルチスレッドをサポートしていません。Google Chromeでも、単一のWebページのJavaScriptを同時に実行することはできません。これは、既存のWebページで大規模な同時実行の問題が発生するためです。Chromeはすべて、複数のコンポーネント(異なるタブ、プラグインなど)を別々のプロセスに分離していますが、1つのページに複数のJavaScriptスレッドがあるとは思えません。

ただし、提案さsetTimeoutれたように、ある種のスケジューリングと「偽の」並行性を許可するために使用できます。これにより、ブラウザーはレンダリングスレッドの制御を取り戻しsetTimeout、指定されたミリ秒後に指定されたJavaScriptコードを開始します。これは、ビューポートでの操作中にビューポート(表示されているもの)を更新できるようにする場合に非常に役立ちます。たとえば座標をループし、それに応じて要素を更新するだけで、開始位置と終了位置だけが表示され、その間に何も表示されません。

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//developer.mozilla.org/presentations/xtech2006/javascript/をご覧ください。


73
決して実装されないというのは、ビジョンが狭すぎると思います。私は最終的にWebアプリが本当にマルチスレッド化できることを保証します(Webアプリがより支配的になり、ハードウェアがより並列になるので、それは論理的です)、そして私がそれを見ると、JavaScriptはWeb開発の事実上の言語なので、最終的にはマルチスレッドをサポートするか、サポートするものに置き換える必要があります。
devios1

6
決して大胆な発言が少し多すぎるとは思わないでしょう:)しかし、真のマルチスレッドjavascriptの利点は予見可能な将来には実現できないと私は思います;)
Kamiel Wanrooij

5
Webワーカーはスレッドモデルよりもプロセスモデルの方が並行性が高いと主張しますが。Webワーカーは、メッセージパッシングを通信手段として使用します。これは、マルチスレッドアプリケーションの「通常の」同時実行問題に対するエレガントなソリューションです。メインページと同じオブジェクトを同時に操作できるかどうかはわかりません。私の知る限り、彼らはDOMにアクセスできません。ただし、これのほとんどはセマンティクスですが、Webワーカーはすべての意図と目的で有望に見えます。
Kamiel Wanrooij

そこにある困難は、追加の可能性よりもはるかに大きなものです。すべての追加の可能性を考えるかどうかはわかりません。ゲームやグラフィックの視覚化のようにwebglが使用される場合を特に考えています。たとえば、Googleマップの新しい3Dバージョンを検討してください。多くの3Dモデルが存在する都市では、多くの家をレンダリングする必要がある場合、私のPCはすべてをロードするのに最大2分必要です。特定の角度では、グラフィックスカードもネットワークも十分に機能していません。ただし、8つのプロセッサーのうちの1つは100%です。次の例に示すように、マルチスレッドはfpsの観点からも大きな懸念事項です
。youtube.com/ watch?v

25

JavaScriptマルチスレッド(制限あり)はこちらです。GoogleはGearsのワーカーを実装し、ワーカーはHTML5に含まれています。ほとんどのブラウザでは、この機能のサポートがすでに追加されています。

ワーカーとの間でやり取りされるすべてのデータがシリアル化/コピーされるため、データのスレッドセーフが保証されます。

詳細については、以下をお読みください。

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

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


8
しかし、それはマルチスレッドではなくマルチプロセスのアプローチではないでしょうか?スレッドは単一のヒープ内で機能することが知られています。
ビーファー

1
@beefeather、それは本当だ。これは、プロセスアプローチの詳細です。
Neil

23

伝統的に、JSは短くて高速に実行されるコードを対象としていました。大きな計算が行われている場合は、サーバー上で計算を行いました。ブラウザで長時間実行され、自明ではないことを実行するJS + HTML アプリのアイデアは、ばかげたことです。

もちろん、今はそれがあります。ただし、ブラウザが追いつくには少し時間がかかります-それらのほとんどはシングルスレッドモデルを中心に設計されており、変更は簡単ではありません。Google Gearsは、バックグラウンド実行を分離することを要求することにより、多くの潜在的な問題を回避します-DOMを変更せず(スレッドセーフではないため)、メインスレッドによって作成されたオブジェクトにアクセスしません(同上)。これは制限的ですが、ブラウザーの設計を簡素化するためと、経験の浅いJSプログラマーがスレッドをいじることを許すことに関連するリスクを減らすため、近い将来、最も実用的な設計になるでしょう...

@marcio

Javascriptでマルチスレッドを実装しない理由は何ですか?プログラマは自分が持っているツールを使って、好きなことを何でもできます。

それでは、他のすべてのWebサイトを開いたときにブラウザーがクラッシュするほど簡単に誤用できるツールを与えないでください。これの素朴な実装は、IE7の開発中にMSに多くの頭痛の種をもたらした領域に直接あなたを連れて行きます:アドオンの作者はスレッドモデルで速くて緩やかに遊んだ結果、オブジェクトのライフサイクルがプライマリスレッドで変更されたときに明らかになる隠れたバグをもたらしました。悪い。IE用のマルチスレッドActiveXアドオンを作成している場合、それは領域に付属していると思います。それ以上の必要があるという意味ではありません。


6
「リスクを軽減>経験の浅いJSコーダーを許可する>スレッドをいじくりまわす」なぜJavascriptにマルチスレッドを実装しないのですか?プログラマは自分が持っているツールを使って、好きなことを何でもできます。それが良いか悪いかは、彼らの問題です。Google Chromeプロセスモデルを使用すると、他のアプリケーションに影響を与えることもできません。:)
Marcio Aguiar

3
@ Shog9-「他のすべてのWebサイトを開いてブラウザがクラッシュするほど誤用しやすい[プログラマ]ツールを提供しないでください。」- 何?同じロジックで、マルチスレッディングを備えた言語はありません。他のすべてのプログラムを開こうとするとクラッシュするためです。それがそのように機能しないことを除いて。スレッディングはほとんどの言語に存在し、ほとんどの初心者プログラマーはそれに触れません。また、スレッディングを本番環境に入れないほとんどのプログラマーや、普及したり広く使用されたりすることのないアプリです。
ArtOfWarfare 2013年

11

この決定の根拠はわかりませんが、setTimeoutを使用してマルチスレッドプログラミングの利点のいくつかをシミュレートできることを知っています。複数のプロセスが同時に物事を行っているような錯覚を与えることができますが、実際にはすべてが1つのスレッドで発生します。

関数に少し仕事をさせて、次のようなものを呼び出します:

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

また、UIの更新、アニメーション画像など、実行する必要のあるその他のことは、機会があったときに発生します。


ほとんどの場合、loop内部を使用する必要がありますが、setTimeoutそれは機能しません。あなたはそのようなことをしましたか、それともハックしましたか?例としては、1000要素の配列の場合、2つのsetTimeout呼び出し内で2つのforループを使用して、最初のループがelementを印刷し0..499、2番目のループがelementを印刷するようにします500..999
benjaminz 2016年

通常、この手法は状態を保存して続行することです。たとえば、0から1000を出力する場合、0から499を出力し、引数500でsetTimeoutトリックを実行します。内部のコードは、引数(500)を受け取り、そこからループを開始します。
Eyal 2017

8

言語がマルチスレッドをサポートしていないのか、ブラウザのJavaScriptエンジンがマルチスレッドをサポートしていないのですか?

最初の質問への答えは、ブラウザーのJavaScriptはサンドボックスで実行され、マシン/ OSに依存しない方法で実行されることを意図しているため、マルチスレッドサポートを追加すると、言語が複雑になり、言語がOSに近づきすぎます。


6

Node.js 10.5以降は、実験的な機能としてワーカースレッドをサポートしています(--experimental-workerフラグを有効にして使用できます):https : //nodejs.org/api/worker_threads.html

したがって、ルールは次のとおりです。

  • I / Oバウンドopsを実行する必要がある場合は、内部メカニズム(別名callback / promise / async-await)を使用します
  • CPUバウンドopsを実行する必要がある場合は、ワーカースレッドを使用します。

ワーカースレッドは、長期間存続するスレッドを対象としています。つまり、バックグラウンドスレッドを生成し、メッセージパッシングを介して通信します。

そうでない場合、無名関数で重いCPU負荷を実行する必要がある場合は、ワーカースレッドを中心に構築された小さなライブラリであるhttps://github.com/wilk/microjobを使用できます。


4

matt bが言ったように、問題はあまり明確ではありません。言語でのマルチスレッドサポートについて質問していると仮定します。これは、現在ブラウザーで実行されているアプリケーションの99.999%では必要ないためです。本当に必要な場合は、回避策があります(window.setTimeoutを使用するなど)。

一般に、マルチスレッド化は、(不変データのみを使用するなど)特別な制限を設けない限り、正しく実行するのは非常に非常に非常に非常に困難です(難しいと言いましたか?)。


3

IntelはJavascriptでのマルチスレッド化に関するオープンソースの研究を行っており、最近GDC 2012で紹介されました。ビデオへのリンクは次のとおりです。研究グループは、主にIntelチップセットとWindows OSに焦点を当てたOpenCLを使用しました。プロジェクトのコード名はRiverTrailで、コードはGitHubで入手できます

さらに役立つリンク:

Webアプリケーション用のコンピューティングハイウェイの構築



1

マルチスレッドをサポートしないのは実装です。現在、Google Gearsは、外部プロセスを実行することで、なんらかの並行性を使用する方法を提供していますが、それはそれだけです。

Googleが本日リリースする予定の新しいブラウザー(Google Chrome)は、プロセス内で分離することにより、コードを並行して実行します。

コア言語はもちろん、Javaなどと同じサポートを持つことができますが、Erlangの並行性のようなもののサポートは地平線のどこにもありません。


1

JavaScriptはシングルスレッド言語です。つまり、1つのコールスタックと1つのメモリヒープがあります。予想通り、コードを順番に実行し、次のコードに移る前にピースコードの実行を終了する必要があります。これは同期ですが、場合によっては有害になることがあります。たとえば、関数の実行にしばらく時間がかかる場合や、何かを待機する必要がある場合、その間すべてがフリーズします。


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によってもたらされるWebワーカーを使用して明らかに可能です。

ウェブワーカーと標準のマルチスレッド環境の主な違いは、メモリリソースがメインスレッドと共有されないこと、オブジェクトへの参照がスレッド間で表示されないことです。スレッドはメッセージを交換することによって通信するため、イベント駆動型の設計パターンに従って、同期および同時メソッド呼び出しアルゴリズムを実装することが可能です。

スレッド間のプログラミングを構築できる多くのフレームワークが存在します。その中には、OODK-JS、並行プログラミングをサポートするOOP jsフレームワークがあります 。https://github.com/GOMServices/oodk-js-oop-for-js


5
メモリの共有とは、個別のプロセス(fork()とexec()など)ではなく、スレッドの正確な定義です。スレッドはオブジェクトを共有できます。プロセスはIPCを使用する必要があります。Webワーカーはマルチスレッドではありません。
felixfbecker 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.