2016-08-11 9 views
7

join()とスレッドを同期させる場合、呼び出しの順序を考慮して、t2の後に出力がt1になるのはなぜですか。スレッド結合C++の動作

すなわち

#include <thread> 

void callFromThread(int id) { 
    int i = 1000; 
    while(i != 0) { 
     printf("%s %d\n", "hi from thread", id); 
     i--; 
    } 
} 

int main(void) { 
    std::thread t1 (callFromThread, 1); 
    std::thread t2 (callFromThread, 2); 

    t1.join(); 
    t2.join(); 

    printf("%s\n", "bye from main!"); 
    return 0; 
} 

私は残りのt2の出力に続いて、残りのすべてのT1の出力に続いて参加通話、前に最初にいくつかのインターリーブを持っていた場合、私は行動の意味を作ることができます。しかし、代わりに私はすべてのt2を見ていますし、すべてのt1を見ています。

+3

参加の順序は、以前の実行履歴とは関係がないためです。特定の実行順序が必要な場合は、なぜスレッドを使用していますか? – EJP

+0

@EJP、それを得るにはしばらく時間がかかりましたが、はい、これは起こっていることの適切な精神モデルです。 – wulfgarpro

答えて

8

joinは、接続しているスレッドではなく、joinという現在のスレッドに影響します。

基本的にjoinは、現在のスレッドが別のスレッドが実行を終了するのを待ちます。他のスレッドの実行がスケジュールされているとき、または他のスレッドと比較してどのような順序になっているかには影響しません。

この例では、スレッドt1t2のどちらが先に実行されて終了するかは保証されません。唯一の保証は、メインスレッドがt1を最初に待ってからt2を待ってから、stdoutにメッセージを記録することです。

+0

それでは、なぜインタリーブされたものは見られないのですか? – wulfgarpro

+0

あなたはコンソール上でインターリーブされていますか? –

+0

はい、私はすべての2つ、1つまたはすべての1を参照している2 – wulfgarpro

1

呼び出しの順番は、同じ方法で出力が順序付けされることを意味するものではなく、「同じ時刻に」スレッドを実行しているため、最初にCPUでintructionが実行される。

t1を強制的にt2の前に作成する必要がある場合は、Semaphoresを使用してください。

1

joinは、それが適用されているスレッドには何の影響も与えません。それは、それが終了するために適用されるスレッドまで呼び出されたスレッドをブロックし、実行を継続します。従って、joinへの呼び出しの順序は、スレッドが実行される順序に何もしません。なお

std::thread t1(callFromthread, 1); 
if (t1.joinable()) t1.join(); 

試験が冗長です。 detachに電話しない限り、std::threadオブジェクトは参加可能です。

+0

'joinable()'に関する情報をありがとう。 – wulfgarpro

+0

結合できないスレッドで 'join'を呼び出すと、定義されていない振る舞いになります。他の開発者がコードを投げ込んだり、システムが新しいスレッドを起動しなかったりすることがあります。 –

+0

@Patrik H、それは私の考えだった – wulfgarpro

1

に参加する順序は、スレッドの実行順序を決定したり影響を与えたりしません。したがって、両方のスレッドからの出力は、任意の順序(またはインターリーブされた状態)になる可能性があります。

+0

スレッドを作成した直後に参加すると、実際には常にジョインの順に実行されます。 – wulfgarpro

+0

はい。しかし、そうすると、実際には実行中のスレッド(結合によってブロックされているメインスレッドを除く)は存在しません。これは、本質的に連続実行であり、マルチスレッド化を打ち負かします。 –

+0

はい、それはあなたの答えを偽っていませんか?実際にスレッドの実行順序を決定しています。 – wulfgarpro

関連する問題