無料で使えるシステムトレードフレームワーク「Jiji」 をリリースしました!

・OANDA Trade APIを利用した、オープンソースのシステムトレードフレームワークです。
・自分だけの取引アルゴリズムで、誰でも、いますぐ、かんたんに、自動取引を開始できます。

setTimeout()で同期化は不要?

setTimeout()で登録した処理の実行は、setTimeout()を呼び出したスレッドとは別のスレッドで、非同期で行われると思っていたのです。(Javaだとそんな感じなので。)なので、setTimeout()で処理をたくさん登録すると、同時実行される可能性があると信じていたわけです。

ところがそんなことはなかった。

var stdout = document.getElementById("stdout");

for ( var i = 0; i < 100; i++ ) {
    (function() { // 変数xを局所化するため、関数で。
        var x = i;
        // 1秒後にxを出力。
        setTimeout( function() {
            stdout.innerHTML += x + ","
        }, 1000 );
    })();
}

番号は必ず順番に出力されます。混ざったりすることはない。確認はこちらから。


また、setTimeout()で実行する処理の途中で実行を待ってみると、それ以降の処理も実行されず、再開が待たされます。

// 一定時間待つ
function wait( time ) {
    var start = new Date();
    stdout.innerHTML += "<br/>wait start. " + start.getTime() + "<br/>";
    while ( true ) {
        var current = new Date();
        if ( current.getTime() - start.getTime() > time ) {
            stdout.innerHTML += "<br/>wait end.  " + current.getTime() + "<br/>";
            return
        } else {
            stdout.innerHTML += ".";
        }
    }
}

for ( var i = 0; i < 100; i++ ) {
    (function() {
        var x = i;
        setTimeout( function() {
            stdout.innerHTML += x + ","
            if ( x == 50 ) {
               // 2000ms待つ。その間setTimeout()に登録した処理の実行は待たされる。
               wait(2000);
            }
        }, 1000 );
    })();
}

確認はこちらから。


さらに、setTimeout()を呼び出したスレッドでも待ってみた。こちらも同様に再開が待たされます。

for ( var i = 0; i < 400; i++ ) {
    (function() {
        var x = i;
        setTimeout( function() {
            stdout.innerHTML += x + ","
        }, 1000 );
    })();
}
// 2000ms待つ。その間setTimeout()に登録した処理の実行は待たされる。
wait( 2000 );

確認はこちらから。

導き出される結論

以上の結果より、setTimeout()の呼び出しも、setTimeout()で登録した処理もすべて同じスレッドで実行されているのではないかと思うにいたったわけです。
※以下は推測です。

  • javascriptのプログラムを実行するスレッドは1つしかいない。(JavaのSwingみたく、イベントディスパッチスレッドのようなスレッドがすべての処理を順番に実行している。)
  • そのため、複数スレッドが同時に変数を変更することは起こりえない。
  • 故にスレッド間の同期化(javaのsynchronizedのような機能)も不要。

どうなんですか? > 誰?

追記 ( 2007-07-03)

HTML5 Working Draft - 28 June 2007の記述に「ブラウザの仕様」として以下がありました。(やっとみつけた・・・。)

4.1.4. Threads
..省略..
All the executable code in a unit of related browsing contexts must execute on a single conceptual thread. The dispatch of events fired by the user agent (e.g. in response to user actions or network activity) and the execution of any scripts associated with timers must be serialised so that for each unit of related browsing contexts there is only one script being executed at a time.
..省略..

この仕様に準拠したブラウザであれば、「シングルスレッドですべてのスクリプトを実行している」、ということみたいです。