0

このコードをコンパイルすると、作成された 99 番目のスレッドが 99 番の複数のスレッドを作成し続けます。代わりに、1 ~ 10 または小さい値を挿入すると、結果はまったく正常になります。

これがコードです。

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

pthread_mutex_t m=PTHREAD_MUTEX_INITIALIZER;
pthread_attr_t attr;

void* test(void *a)
{
    int i=*((int *)a);
    printf("The thread %d has started.\n",i);
    pthread_mutex_lock(&m);
    usleep(10000);
    printf("The thread %d has finished.\n",i);
    pthread_mutex_unlock(&m);
    pthread_exit(NULL);

}

int main()
{
    int i=0,j=0;
    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);
    pthread_t thread[100];

    for (i=0;i<100;i++)
    {
        j=i;
        pthread_create(&thread[i],&attr,test,&j);

    }

    for (i=0;i<100;i++)
        pthread_join(thread[i],NULL);
    return 0;
}

私は得る:

..../*Normal Results*/
The thread 99 has finished.
The thread 99 has finished.
The thread 99 has finished.
The thread 99 has finished.
The thread 99 has finished.
The thread 99 has finished.

なぜこうなった?

4

4 に答える 4

1

j各スレッドには、メイン スレッドの同じスタック位置 ( ) への同じポインタが渡されます。さらに同期しないと、各スレッドがいつスケジュールされ、jその値を出力する前に実行およびアクセスされるかが未定義になります。

各スレッドから一意の番号を出力する方法はたくさんあります。

  1. メインスレッドでこの番号を含む (またはこの番号である) 構造体を malloc します。それを解放する役割を持つ子スレッドに渡します
  2. (Brian Roche による以下の提案) 値 0、1、2 などを持つ 100 個の int の配列を宣言します。異なる配列項目のアドレスを各スレッドに渡します。
  3. 各スレッドにミューテックスをロックさせてから、グローバルカウンターをコピー/インクリメントします。ミューテックスは、スレッドまたは別のグローバルに渡すことができます
  4. セマフォを各スレッドに渡し、番号がアクセスされると通知します。メインスレッドでこのセマフォを待ちます

オプション 3 と 4 には、スレッドの起動のシリアル化が含まれることに注意してください。これをたくさん行うと、複数のスレッドを実行してもほとんど意味がありません!

于 2013-01-03T20:13:15.113 に答える
1

すべての theadIds を保持する必要があります

int indexes[PTHREAD_COUNT];

for (i=0;i<100;i++) {
    indexes[i] = i;
    pthread_create(&thread[i], &attr, test, &indexes[i]);
}
于 2013-01-03T20:17:17.650 に答える
0

iメインコードと同じアドレスjであり、スレッドで 30 ミリ秒スリープします。したがって、すべてのスレッドは最初のミューテックス呼び出しまで実行する時間があります。その後、すべてのスレッドが (少しだけ) 30 ミリ秒停止し、終了したことを出力します。もちろん、ipthread_join ループが終了したため、メイン ループは 99 になりました。

「j」値の配列が必要です [すべてのスレッドを個別に実行したい場合]。または、何か他のことをします。それはすべて、あなたが実際にやりたいことにかかっています。

于 2013-01-03T20:19:21.697 に答える
0

データ a へのポインタとして同じメモリ位置 (&j) を渡しています。

スレッドが開始すると、j に割り当てられたばかりの値が出力されますが、これは問題ないようです。

しかし、ロックを取得してスリープ状態になったのは 1 つだけで、他のすべてはブロックされました。悪夢が終わったとき、もちろん、メモリ位置「a」の int 値は 99 です。

于 2013-01-03T20:20:14.510 に答える