2016-04-05 13 views
3

私はプロデューサーとコンシューマーの問題に取り組んでいます。私は、束縛されたバッファに物を入れ、複数の消費者を使ってバッファからデータを取得するために、1つのプロデューサを作成しました。すべての消費者が働いているかどうかを確認するために、私はそれぞれの人にIDを与え、それを印刷させます。C pthread:複数のスレッドがありますが、1つのスレッドのみが使用されます

以下は、複数のコンシューマを作成するためのコードです。私はのように見えるかもしれ期待何

#define CONSUMER_NUM 5; 
pthread_t consumer[CONSUMER_NUM]; 
for(i=0;i<CONSUMER_NUM;i++){ 
    int t = i; 
    pthread_create(&consumer[i],NULL,fun_consumer,(void*)&t); 
} // pass i to the function fun_consumer to be an id of the thread 

Consumer 1 
Consumer 2 
Consumer 3 
Consumer 4 
Consumer 5 

は、私は、出力は通常、スレッドのランダム実行にこの原因のように見えないであろうことを理解しています。私がここで期待したのは、消費者のほとんどが仕事に就くということです。しかし、真実はこのように印刷されたプログラムです:

Consumer 5 
Consumer 5 
Consumer 5 
Consumer 5 
Consumer 5 

ここでは消費者は1つだけです。私は "スリープ"を試みましたが、それは私に期待した出力を与えることができますが、実行が遅くなりました。私はこの問題を解決するためのより良い方法があるかどうか疑問に思っていますか?

答えて

2

すべてのスレッドにローカル変数iへのポインタを与えています。各ループの繰り返しでは、iが変化しています。スレッドが実際に起動され、準備完了ループが実行され、iは5(最終値)になります。

しかし、これは多くの潜在的な結果のほんの1つです。あなたのスレッドIDは、このコードで古典的なデータ競争があるので、実際に何かを読むことができます。どのような方法でも保護されていない複数のスレッドから変数にアクセスしています。運があればこのようにして42を読むかもしれない。

解決策。 スレッドごとに新しい変数を動的に作成し、この変数のアドレス(メモリリークを防ぐためにスレッド内で削除する必要がある)を渡すか、整数変数をポインタに変換してこの値をスレッドに渡します。これを(多少)移植するには、iは実際にはunsigned intではなくuintptr_tのタイプである必要があります。

たびに作成することができますどのように新しい変数の例:

for (i=0 ; i<CONSUMER_NUM; ++i) { 
    int* id = malloc(sizeof(int)); 
    *id = i; 
    pthread_create(&consumer[i],NULL,fun_consumer, id); 
} 
... 
void* fun_consumer(void* arg) { 
    int id = *(int*)(arg); 
    free(arg) 
    // rest of code 
+0

感謝を!私は最初の方法を試してコードを変更しましたが(上記のように私はそれを編集しましたが)、それでもすべてが5で出力されます... –

+0

@IvyLin、あなたは私が言ったことを理解できませんでした。変更を続ける変数のアドレスを提供しています。コードで私の更新答えをご覧ください。 – SergeyA

+0

私は見る!あなたの忍耐をありがとう、それは今動作します:) @ SergeyA –

1

これらの変数には、ループ内で変化する変数iへの参照を与えます。すべてのスレッドがそれを5と見なすほど速く実行します。

まだ5つのスレッドがありますが、番号を間違って送信しています。