質問
私はnスレッドを作成し、バリアの故障後に実行を開始します。
グローバルデータ分野:
int bkdown = 0;
main():
pthread_barrier_init(&bar,NULL,n);
for(i=0;i<n;i++)
{
pthread_create(&threadIdArray[i],NULL,runner,NULL);
if(i==n-2)printf("breakdown imminent!\n");
if(i==n-1)printf("breakdown already occurred!\n");
}
スレッドランナー関数:
void *runner(void *param)
{
pthread_barrier_wait(&bar);
if(bkdown==0){bkdown=1;printf("barrier broken down!\n");}
...
pthread_exit(NULL);
}
予想される注文:
breakdown imminent!
barrier broken down!
breakdown already occurred!
実際の注文: (繰り返しテスト)
breakdown imminent!
breakdown already occurred!
barrier broken down!!
誰かが私が手に入れていない理由を説明できますか "broken down"
の前のメッセージ "already occurred"
メッセージ?
解決
for(i=0;i<n;i++)
{
pthread_create(&threadIdArray[i],NULL,runner,NULL);
if(i==n-2)printf("breakdown imminent!\n");
if(i==n-1)printf("breakdown already occurred!\n");
}
このループの実行を止めるものはありません i == n-1
。 pthread_create()は、実行するスレッドを発射するだけです。開始または終了するのが待ちません。したがって、スケジューラに翻弄されているため、ループの実行を続けるか、新しく作成されたスレッドの1つに切り替えることができます(またはSMPシステムで両方を実行します)。
また、障壁を無効にしています n
, 、したがって、いずれにせよ、すべてのスレッドを作成するまで、スレッドは障壁を乗り越えません。
他のヒント
スレッドが実行される順序は、オペレーティングシステムに依存します。スレッドを起動するからといって、OSがすぐに実行されるわけではありません。
スレッドが実行される順序を本当に制御する場合は、そこに何らかの同期を置く必要があります(ミューテックスまたは条件変数を使用してください。)
NOSとStarKeyの回答に加えて、あなたはあなたのコードに別のシリアル化があることを考慮する必要があります。 FILE
変数、つまり stdin
.
その変数へのアクセスは内部的に変異し、あなたの順序は n+1
スレッド(呼び出しスレッドを含む)は、そのMutexが定義されている実装であることにアクセスし、基本的にランダムにしてください。
だからあなたがあなたを手に入れる順序 printf
出力とは、スレッドがこれらのワームホールを通過する順序です。
2つの方法のいずれかで期待される順序を取得できます
- メインスレッドよりも優先度が高い各スレッドを作成します。これにより、作成直後に新しいスレッドが実行され、障壁が待機することが保証されます。
- PTHREAD_CREATE()の前に「BreakDown -Imnint! n」を移動し、PTHREAD_CREATE()ごとにsched_yield()呼び出しを使用します。これにより、新しく作成されたスレッドが実行されます。