質問

私は現在POSIXスレッドについて学んでいますが、これはマルチスレッドに関する一般的な質問であると思います。私が取り組んでいる本から、競合状態を示すこの例があります:

void *thread_main(void *thread_number) {
    printf("In thread number %d.\n", *(int *)thread_number);
}

void main() {
    int i = 0;
    pthread_t thread;

    for( i = 0; i < 10; i++ ) {
        printf("Creating thread %d.\n");
        pthread_create(&thread, 0, thread_main, &i);
        printf("Created thread %d.\n");
    }
}

これについて理解していないことがいくつかあります。まず、「スレッド番号5で」スレッド番号5にあるはずがないにもかかわらず、何度も印刷されます。本では、スレッド8が何度も印刷される例を示しています。また、 *(int *)thread_number と書かれている部分もわかりません。これを単にthread_numberに変更しようとしましたが、それは何度も何度も奇妙な数字を与えてくれました。

この本は実際にこれを説明していません。誰かがここで何が起こっているのか明確に説明してもらえますか?次のようなものが印刷されない理由がわかりません:

> Creating thread 1.
> In thread number 1.
> Created thread 1.
> Creating thread 2.
> In thread number 2.
> Created thread 2.

マルチスレッドであるため、「スレッド番号xで」ということを知っています。一部は異なる時間に来るでしょうが、なぜ「スレッド番号xに」が正確に10でないのか、私には本当に分かりません。作成したスレッドごとに1行で!

〜desi

役に立ちましたか?

解決

まず、*(int *)thread_numberはポインターです-thread_numberを取得したばかりのとき、「ストレンジ番号」は main 関数からの「i」へのポインターアドレスでした(そして、間違っています。プログラムの1回の実行ですべて同じ番号である必要があります(したがって、10個のスレッドのそれぞれが同じ「スレッド番号[番号]」である必要があります)。

これらは意味のある繰り返し5のポインタである-各スレッドは main 関数から同じ基になるiで動作していたことを理解する必要があります-新しいスレッドごとにコピーされていません、したがって、 main 関数でiがインクリメントされたとき、それは thread_main 関数のthread_numberに反映されました。

最後のパズルのピースは、各新しいスレッドのセットアップ時間とコンテキスト切り替え(実際に実行されているスレッドの変更)がすぐに行われないことです。したがって、あなたの場合、forループは新しく作成されたスレッドの5回前に実行されます実際に実行され(本の場合、forループはコンテキスト切り替えの8回前に実行されます)、各スレッドは同じ基になるi値(現在は5)を参照します。

他のヒント

作成された10個のスレッドのいずれかが実行される前に、forループが10回繰り返される可能性があります。その場合、 * thread_number の値は、スレッドごとに10になります(単一の値を持つ単一のメモリ位置へのポインタであるため)。

i へのポインターを pthread_create に渡さない場合、 int の値はアドレスとして扱われます、したがって、 thread_main でそれを間接参照すると、任意のメモリ位置にアクセスしていることになり、その内容はおそらく未定義です。その場合、セグメンテーション違反ではないことは幸運です。

各スレッドで * thread_number の正しい値を確認するには、 int を呼び出してから int code> pthread_create に、次のように i の現在の値を割り当てます。

for( i = 0; i < 10; i++ ) {
    int *thread_count = malloc(sizeof(int));
    *thread_count = i;
    printf("Creating thread %d.\n", i);
    pthread_create(&thread, 0, thread_main, thread_count);
    printf("Created thread %d.\n", i);
}

もちろん、次のように、スレッドが終了したらメモリを free する必要があります:

void *thread_main(void *thread_number) {
    printf("In thread number %d.\n", *(int *)thread_number);
    free(thread_numbr);
}

まず、競合状態は悪いことです。このプログラムは期待どおりに動作しないはずです 。競合状態とは、プログラムが中断するように設計されていることを意味します。

この場合、すべてのスレッドが変数 i 共有しているように見えます。単一の共有変数への参照を渡し、スケジュールされたときに報告しようとします。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top