3

私は次のコードを持っています:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

#define LOOPS 10000

void *run(void *arg)
{
    int id = strtol(arg,NULL,0);
    int i;
    for(i=0; i<LOOPS; i++)
    {
        printf("In %d.\n",id);
    }
}

int main()
{
    pthread_t p1,p2;
    void *res;

    pthread_create(&p1,NULL,run,"1");
    pthread_create(&p2,NULL,run,"2");
    pthread_join(p1,&res);
    pthread_join(p2,&res);
    return 0;
}

これを実行すると、文字列「In1」が10000回連続して表示され、次に「In2」が10000回連続して表示されるか、またはその逆になります。ここにあるように、文字列が交互に表示されたり、連続して表示されたりするべきではありませんか?

4

3 に答える 3

8

スレッドがスケジューラーによってインターリーブされる順序は決定論的ではありません(...まあ、それはスケジューラー/カーネルの観点からのみです)。注文について推測するべきではありません。

この状況では、スケジューラー->プリエンプトして他のスレッドの実行を許可する前に、いずれかのスレッドが作業全体を完了することが許可されていることがわかります。

于 2013-02-17T17:51:36.070 に答える
2

スケジューラはタイムスロットでプロセスを実行します。タイムスロットは、効率的になるのに十分な大きさですが、同時実行の錯覚を与えるのに十分小さいです。

マルチコア CPU では、OS カーネル レベルで実装されたスレッドは、実際には並列で実行されます。

これに加えて、1 回の小さな書き込みを行うのに必要な処理能力とほぼ同じ量の処理能力が 1 回の大きな書き込みを行うのに必要なため、出力がバッファリングされることがあります。出力が対話型端末デバイスに送られる場合、ほとんどのシステムではバッファリングが無効になっていますが、環境の詳細が重要になり始めています。

出力をインターリーブするには、出力行を生成したという理由だけで、マルチコアまたは非常にきめ細かく、高価なコンテキスト スイッチを喜んで実行するスケジューラでバッファリングされずに実行される必要があります。マルチコアの場合、ライブラリとカーネルを通る実行パスは、偶然にも 3 つのコアでバランスを取る必要があります。それはおそらく決して起こらないでしょう。

結局のところ、一度に 1 つずつ作成しているので、一方は常に他方より先に実行する準備ができています。

于 2013-02-17T18:04:53.857 に答える
2

他の2つの答えは正しいですが、これを追加したいと思います:

2 つの出力インターリーブされます。それらは1行または2行ごとにインターリーブされているわけではなく、おそらく数千行ごとにインターリーブされています。各スレッドに時間量が与えられると、数千行を出力する時間があります。各スレッドで 10,000 行しか出力しないため、一方が他方の作業を開始する前に作業を終了する時間があります。

forループを無限ループに置き換えてみて、何が起こるかを観察してください。

于 2013-02-17T18:08:25.453 に答える