JavaScriptでの共有メモリの紹介
共有メモリ JavaScriptの高度な機能であり、スレッド(プロセスの同時実行部分)が活用できることです。記憶手段を共有する 更新されたデータをスレッド間で受け渡すという問題がない すべてのスレッドが共有メモリ内の同じデータにアクセスして更新できる.
それは素敵ではありませんか?よくほとんど。この記事では、私たちは見るでしょう JavaScriptで共有メモリを使用する方法 そしてこれがあなたが本当にやりたいことであるかどうかを決める方法.
共有メモリの長所と短所
を使用しております ウェブワーカー に JavaScriptでスレッドを作成する. Web Workers APIを使用すると、次のことに使用できるワーカースレッドを作成できます。 バックグラウンドでコードを実行する メインスレッドが自由に実行を継続できるように、おそらくUIイベントを処理し、UIがフリーズしないようにします。.
ワーカースレッド メインスレッドと同時に実行します。. タスクの異なる部分をこのように同時に実行すると、時間が節約されます。あなたはより早く終えるが、それはまたそれ自身の問題のセットを持っている.
各スレッドを確認する 必要なリソースを取得し、タイムリーに互いに通信する それ自体がタスクであり、そこでの誤操作は驚くべき結果をもたらす可能性があります。または、 1つのスレッドがデータを変更しており、別のスレッドがそれを読み取っています 同時に, あなたは他のスレッドが何を見ると思いますか?更新または古いデータ?
しかし、Webワーカーはめちゃくちゃに簡単ではありません。メッセージを使用して通信している間、お互いに送信するデータは オリジナルではなくコピー, そうではないという意味 シェア 同じデータ。彼ら データのコピーを互いに渡す 必要に応じて.
しかし、共有は気にしているので、複数のスレッドが同じデータを同時に調べて変更する必要もあるかもしれません。そう, 共有を禁止することは大したことではありません. これはどこです SharedArrayBuffer
物が絵に入ってくる。それは私たちをさせるでしょう 複数のスレッド間でバイナリデータを共有する.
の SharedArrayBuffer
物
スレッド間でデータコピーを渡すのではなく、 のコピーを渡す SharedArrayBuffer
物. A SharedArrayBuffer
物 データが保存されているメモリを指します。.
そのため、 SharedArrayBuffer
スレッド間で渡される すべてはまだ同じメモリを指します。 元のデータが保存されている場所。したがって、スレッドは 同じメモリ内のデータを表示および更新する.
ウェブワーカー なしで 共有メモリ
共有メモリを使用せずにWebワーカーがどのように機能するのかを確認するには、 ワーカースレッドを作成する そして データを渡す.
の index.html
ファイルは メインスクリプト の中 あなたがそれを以下で見ることができるように、タグ:
const w = new Worker( 'worker.js'); var n = 9; w.postMessage(n);
の worker.js
ファイルは ワーカースクリプト:
onmessage =(e)=> console.group( '[worker]'); console.log( 'メインスレッドから受信したデータ:%i'、e.data); console.groupEnd();
上記のコードを使用すると、次のようになります。 コンソールに出力:
[worker]メインスレッドから受信したデータ:9
上記のスニペットの完全なコード説明については、Webワーカーに関する私の前述の投稿を読むことができます。.
今のところ、データは スレッド間でやり取りされる を使用して postMessage()
方法。データは 反対側に メッセージ
イベントハンドラ, イベントの値として データ
財産.
今、私たちは データを変更する 受信側で更新されたように見えますか?どれどれ:
const w = new Worker( 'worker.js'); var n = 9; w.postMessage(n); n = 1。
予想通り、 データがあります ではない 更新されました:
[worker]メインスレッドから受信したデータ:9
それはどうしてでしょうか。それは メインスクリプトからワーカーに送られた単なるクローン.
ウェブワーカー と 共有メモリ
今、私たちは 使用 SharedArrayBuffer
物 同じ例で。私達は新しいを作成できます SharedArrayBuffer
インスタンス化 を使用して 新しい
キーワード. コンストラクターは1つのパラメーターを取ります。ある バイト単位の長さ値, バッファサイズを指定する.
const w = new Worker( 'worker.js'); buff = new SharedArrayBuffer(1); var arr = new Int8Array(buff); / *設定データ* / arr [0] = 9; / *バッファ(コピー)をワーカーに送信しています* / w.postMessage(buff);
に注意してください SharedArrayBuffer
物 共有メモリ領域のみを表します。. に バイナリデータを見て変更する, 適切なデータ構造を使用する必要があります。 TypedArray
または データビュー
オブジェクト).
の中に index.html
上記のファイル、新しい SharedArrayBuffer
1バイト長で作成されます。その後、新しい Int8Array
, の一種です TypedArray
オブジェクトは、に使用されます データを “9” 提供されたバイトスペース内.
onmessage =(e)=> var arr = new Int8Array(e.data); console.group( '[worker]'); console.log( 'メインスレッドから受信したデータ:%i'、arr [0]); console.groupEnd();
Int8Array
労働者にも使われる バッファ内のデータを見る.
の 期待値がコンソールに表示されます。 ワーカースレッドから。これはまさに私たちが望んでいたものです。
[worker]メインスレッドから受信したデータ:9
それでは、ましょう メインスレッドのデータを更新する 変更が労働者に反映されているかどうかを確認する.
const w = new Worker( 'worker.js')、buff = new SharedArrayBuffer(1); var arr = new Int8Array(buff); / *設定データ* / arr [0] = 9; / *バッファ(コピー)をワーカーに送信しています* / w.postMessage(buff); / *データの変更* / arr [0] = 1;
そして、あなたが以下で見ることができるように、アップデートは 労働者の内側に反映するか!
[worker]メインスレッドから受信したデータ:1
しかし、コードも 逆の方法で対処する必要がある:労働者の価値が最初に変わるとき、それは また更新する必要があります メインスレッドから印刷したとき.
この場合、コードは次のようになります。
onmessage =(e)=> var arr = new Int8Array(e.data); console.group( '[worker]'); console.log( 'メインスレッドから受信したデータ:%i'、arr [0]); console.groupEnd(); / *データの変更* / arr [0] = 7; / *メインスレッドへの投稿* / postMessage( ");
の ワーカー内でデータが変更された と 空のメッセージがメインスレッドに投稿されます バッファ内のデータが変更され、メインスレッドを出力する準備が整ったことを知らせる.
const w = new Worker( 'worker.js')、buff = new SharedArrayBuffer(1); var arr = new Int8Array(buff); / *設定データ* / arr [0] = 9; / *バッファ(コピー)をワーカーに送信しています* / w.postMessage(buff); / *データの変更* / arr [0] = 1; / *ワーカーが変更した後のデータの印刷* / w.onmessage =(e)=> console.group( '[main]'); console.log( 'ワーカースレッドから受信した更新データ:%i'、arr [0]); console.groupEnd();
そして、これもうまくいきます! バッファ内のデータはワーカー内のデータと同じです.
[worker]メインスレッドから受け取ったデータ:1 [main]ワーカースレッドから受け取った更新データ:7
値 どちらの場合も更新されているようです;メインスレッドとワーカースレッドの両方が同じデータを表示および変更している.
最後の言葉
先に述べたように、JavaScriptで共有メモリを使う 欠点がないわけではない. それを確実にするのは開発者次第です。 実行順序は予測どおりに行われる 誰がトロフィーを取るかについて誰も知らないので、2つのスレッドが同じデータを取得するために競合していることはありません。.
共有メモリにもっと興味があるなら、のドキュメントを見てください。 アトミック
オブジェクトの Atomicsオブジェクトはいくつかの困難を解決するのに役立ちます, 共有メモリに対する読み書きの予測不可能な性質を減らすことによって.