112

私はこのリンクを見ました:JavaScriptでの相互排除の実装。一方、javascriptにはスレッドがないことを読みましたが、それは正確にはどういう意味ですか?

イベントが発生した場合、コードのどこで割り込みできますか?

また、JSにスレッドがない場合、JSでミューテックスを使用する必要がありますか?

setTimeout()具体的には、とによって呼び出される関数を使用すると、グローバルにアクセス可能な変数にどのような影響があるXmlHttpRequestのか​​疑問に思っています。onreadystatechange

4

7 に答える 7

111

Javascriptはリエントラント言語として定義されています。つまり、ユーザーに公開されるスレッドはなく、実装にスレッドが存在する可能性があります。非同期コールバックのような関数setTimeout()は、スクリプトエンジンがスリープするのを待ってから、実行できるようにする必要があります。

つまり、イベントで発生するすべてのことは、次のイベントが処理される前に終了する必要があります。

そうは言っても、非同期イベントが発生したときとコールバックが呼び出されたときの間で値が変化しないことをコードが期待する場合は、ミューテックスが必要になることがあります。

たとえば、1つのボタンをクリックして、コールバックを呼び出すXmlHttpRequestを送信するデータ構造がある場合、破壊的な方法でデータ構造を変更し、イベントが発生したときと同じデータ構造を直接変更する別のボタンがあります。起動され、コールバックが実行されたときに、ユーザーはコールバックの前にデータ構造をクリックして更新し、値を失う可能性がありました。

このような競合状態を作成することはできますが、各関数はアトミックであるため、コードでそれを防ぐのは非常に簡単です。実際に競合状態を作成するには、多くの作業が必要であり、いくつかの奇妙なコーディングパターンが必要になります。

于 2008-09-24T01:04:31.787 に答える
22

この質問への回答は、与えられた時点では正しいものの、少し時代遅れです。また、Webworkerを使用しないクライアント側のjavascriptアプリケーションを見る場合でも、正しいです。

Webワーカーに関する記事:Webワーカー
を使用したJavaScriptでのマルチスレッドWebワーカーでの
Mozilla

これは、web-workersを介したjavascriptにマルチスレッド機能があることを明確に示しています。質問に関しては、javascriptでミューテックスが必要ですか?これはよくわかりません。しかし、このスタックオーバーフローの投稿は関連しているようです:
N非同期スレッドの相互排除

于 2011-02-22T14:21:08.007 に答える
8

@ウィリアムが指摘するように、

非同期イベントが発生したときとコールバックが呼び出されたときとの間で値が変化しないことをコードが期待する何かを行う場合、mutex が必要になることがあります。

これはさらに一般化できます。コードが、非同期リクエストが解決されるまでリソースの排他的制御を期待する何かを行う場合、ミューテックスが必要になる場合があります。

簡単な例は、バックエンドでレコードを作成するために ajax 呼び出しを起動するボタンがある場合です。幸せなユーザーがクリックして離れて複数のレコードが作成されるのを防ぐために、少しのコードが必要になる場合があります。この問題にはいくつかのアプローチがあります (たとえば、ボタンを無効にする、ajax 成功時に有効にする)。単純なロックを使用することもできます。

var save_lock = false;
$('#save_button').click(function(){
    if(!save_lock){
        //lock
        save_lock=true;
        $.ajax({
            success:function()
                //unlock
                save_lock = false;  
            }
        });
    }
}

それが最善のアプローチであるかどうかはわかりません。他の人がjavascriptで相互排除をどのように処理するかを知りたいと思いますが、私が知る限り、それは単純なミューテックスであり、便利です。

于 2011-07-20T09:53:40.520 に答える
7

はい、 localStorageのように、タブ/ウィンドウ間で共有されるリソースにアクセスするときに Javascript でミューテックスが必要になる場合があります。

たとえば、ユーザーが 2 つのタブを開いている場合、次のような単純なコードは安全ではありません。

function appendToList(item) {
    var list = localStorage["myKey"];
    if (list) {
        list += "," + item;
    }
    else {
        list = item;
    }
    localStorage["myKey"] = list;
}

localStorage 項目が「取得」されてから「設定」されるまでの間に、別のタブが値を変更した可能性があります。一般的にはありそうにありませんが、可能です。特定の状況での競合に関連する可能性とリスクを自分で判断する必要があります。

詳細については、次の記事を参照してください。

于 2018-02-08T17:35:31.217 に答える
3

JavaScriptはシングルスレッドです...Chromeは新しい獣かもしれませんが(シングルスレッドでもあると思いますが、各タブには独自のJavaScriptスレッドがあります...詳細には調べていないので、引用しないでくださいそこの)。

ただし、心配する必要があることの1つは、JavaScriptが、送信した順序とは異なる複数のajaxリクエストをどのように処理するかということです。したがって、本当に心配する必要があるのは、結果が送信した順序とは異なる順序で戻ってきた場合に、ajax呼び出しがお互いの足を踏まないように処理されるようにすることだけです。

これはタイムアウトにも当てはまります...

JavaScriptがマルチスレッド化するとき、ミューテックスなどについて心配するかもしれません。

于 2008-09-24T00:55:41.947 に答える
2

言語である JavaScript は、必要に応じてマルチスレッド化できますが、JavaScript エンジンのブラウザー埋め込みは、一度に (おそらくタブごとに) 1 つのコールバック (onload、onfocus、<script> など) しか実行しません。コールバックの登録と受信の間の変更にミューテックスを使用するという William の提案は、このため、文字通りに受け取られるべきではありません。これは、ロックを解除するコールバックが現在のコールバックの背後でブロックされるため、介在するコールバックでブロックしたくないためです。 ! (うわー、英語はスレッド化について話すのが苦手です。) この場合、フラグが設定されている場合、文字どおりに、または setTimeout() のようなものを使用して、現在のイベントを再ディスパッチするという行に沿って何かをしたいと思うでしょう。

JS の別の埋め込みを使用していて、一度に複数のスレッドを実行する場合は、もう少し厄介なことになる可能性がありますが、JS がコールバックを非常に簡単に使用でき、プロパティ アクセスでオブジェクトをロックできるため、明示的なロックはほとんど必要ありません。 . しかし、マルチスレッドを使用する一般的なコード (ゲーム スクリプトなど) 用に設計された埋め込みが、明示的なロック プリミティブも提供しないとしたら、私は驚くでしょう。

テキストの壁でごめんなさい!

于 2008-11-28T05:47:00.070 に答える
-1

イベントは通知されますが、JavaScript の実行は依然としてシングルスレッドです。

私の理解では、イベントが通知されると、エンジンは現在実行しているものを停止してイベントハンドラーを実行します。ハンドラーが終了すると、スクリプトの実行が再開されます。イベント ハンドラーがいくつかの共有変数を変更した場合、再開されたコードでは、これらの変更が「突然」表示されます。

共有データを「保護」したい場合は、単純なブール値フラグで十分です。

于 2008-09-24T01:04:33.800 に答える