2

私は今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」がマルチスレッド化されているので、私はそれを知っています。一部は異なる時期に提供されますが、作成したスレッドごとに1行の「スレッド番号x」が正確に10個ない理由がわかりません。

〜desi

4

3 に答える 3

3

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

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

*thread_number各スレッドでの正しい値を確認したい場合は、呼び出す前にmalloc新しい値を作成し、次のように現在の値を割り当てます。intpthread_createi

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);
}
于 2009-01-06T12:13:29.803 に答える
3

最初に *(int *)thread_number はポインタのものです - thread_number を持っていたとき、「奇妙な数字」はメイン関数からの「i」へのポインタアドレスでした (そして、私が間違っていない限り、それらはすべてプログラムの 1 回の実行で同じ番号 (つまり、10 個のスレッドのそれぞれに同じ "In thread number [番号]" があるはずです))。

意味をなすために、これらは繰り返される 5 のポインターであることを理解する必要があります。これは、 thread_main関数のthread_numberに反映されました。

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

于 2009-01-06T12:27:26.220 に答える
1

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

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

于 2009-01-06T12:13:02.177 に答える