61

アトミックなテスト アンド セット、セマフォ、Javascript のロックなどはありますか?

カスタムプロトコルを介して非同期バックグラウンドプロセスを呼び出すjavascriptがあります(バックグラウンドプロセスは文字通り、ブラウザとは無関係の別のプロセスで実行されます)。競合状態に陥っていると思います。テストとセットの間でバックグラウンド プロセスが返され、javascript 側で問題が発生します。実際のセマフォにするには、テストと設定の操作が必要です。

バックグラウンド プロセスを検出してキューに入れようとする JavaScript コードは次のとおりです。

Call = function () {

var isRunning = true,
    queue = [];

return  {
    // myPublicProperty: "something",

    call: function (method) {
            if (isRunning) {
                console.log("Busy, pushing " + method);
                queue.push(method);
            } else {
                isRunning = true;
                objccall(method);
            }
        },

        done: function() {
            isRunning = false;
            if (queue.length > 0) {
                Call.call(queue.shift());
            }
        }
    };
}();

Call は、キューイングを実装するシングルトンです。外部プロセスを呼び出したい人は誰でも Call.call("something") を行います。

何か案は?

4

7 に答える 7

26

JS はマルチスレッド言語ではないため、JavaScript にはロック セマンティクスがありません。複数のスレッドは、完全に異なるコンテキストでのみ同時に動作できます。HTML5 ワーカー スレッド、または JavaScriptCore API のコンテキスト オブジェクトの複数のインスタンスのようなもの (SpiderMonkey にも同様の概念があると思います)。状態を共有することはできないため、本質的にすべての実行はアトミックです。

さて、コードの一部を提供したので、次のようなものがあると思います:

External Process:
<JSObject>.isRunning = true;
doSomething()
<JSObject>.done()

またはそのようなもの(適切なAPIを使用)。その場合、JS が js オブジェクトのコンテキストで実行されている場合 (JavaScriptCore が行うこと)、JS エンジンがブロックされることが予想されます。失敗すると、おそらく js 実行の周りに手動ロックを配置する必要があります。

これらすべてを行うためにどのエンジンを使用していますか? あなたの説明に基づいて、その言語によって提供される C/C++ API を使用して、非 JS 言語のセカンダリ スレッドからフラグを設定しているように聞こえます。ほとんどの JS エンジンは、API を介して行われた状態操作が通常、すべての実行が行われるのと同じスレッドである単一のスレッドで発生します。

于 2009-02-17T01:19:40.340 に答える
2

まず第一に、javaScript がシングル スレッドであることは事実ですが、javaScript アプリケーションでシリアル化メカニズムがまったく必要ないことは事実ではありません。

簡単な例としては、サーバーへの Ajax リクエストが動作している間に、送信ボタンが一定時間フェードアウトする場合があります。非同期 Ajax リクエストが正常に完了すると、ボタンがあった場所にメッセージが表示されます。

Ajax リクエストが完了するとすぐに、ボタンのフェードアウトをキャンセルし、そのスタイルを「display: none」に設定するだけでよいのですが、jQuery ではそれができません。また、イベントを使用して 2 つの同時アクティビティを同期するソリューションも考えられますが、これは単純な問題としては本質的にやり過ぎです。

ローテクな解決策は、ロックをポーリングし、フェードアウトが完了するとロックが解除されますが、$.post で設定された成功コールバックが実行されるまで、「サーバー完了」メッセージは表示されません。

var gl_lock;
var gl_selfID;

function poll_lock(message) {
     if (gl_lock === 0) {
          $('#output').text(message).fadeIn(200);
          window.clearInterval(gl_selfID);
     }
 } // end of poll_lock

 function worker() {

     // no one gets in or out
     gl_lock = 1;

     $.post(..., data,function() { 
           gl_selfID = window.setInterval(poll_lock, 40, data.message);
      }, "json");

     // end of fadeout unlock the semaphore
     $('#submit-button').fadeOut(400, function() { gl_lock = 0; });

  } // end of worker

最後に、これは perrohunter によるこのディスカッションで以前に提案された行に沿った、より詳細な回答だと思います。

于 2015-10-04T00:24:03.167 に答える
2

おそらく、基本的な整数セマフォを実装できます。変数をDOMに追加してロック/ロック解除し、関数がそれをチェックし続けるようにし、そうでない場合はタイムアウトします=)

Mootools などのフレームワークを使用している場合は、onComplete などのイベントでアプリのフローを処理することができます。

于 2009-02-17T01:16:15.840 に答える
0

選択リストにデータを入力する ajax があり、ロックする必要があったので、このようなことをしました。遅延オブジェクトやパイプなどを使用しても、おそらくもっと簡単にできると思います。

var semaphore=[];

function myFunc(arg){
   var dfd;
   $.when(semaphore[table]).done(
      function(){
            dfd=myFuncInner(arg);
      }
      );
return dfd;
}

function myFuncInner(table){
semaphore[arg] = new $.Deferred();
... 
somethingasynchronous({
    semaphore[arg].resolve();
});

return  semaphore[arg];
}
于 2014-06-08T22:33:32.120 に答える