2016-05-08 6 views
0

私はスレッドを使用して計算を行う必要がある大学の割り当てがあります。それは、複数の生産者を持つ1つの消費者にまで沸き立ちます。>各生産者は1つの計算を行い、消費者はそれをすべて一緒に追加します。C - Pthreads、1つのコンシューマ、複数のプロデューサ同期

プロデューサーがクリエイティブを計算してクリティカルセクションを終了するたびにプロデューサーがクリティカルセクションに入るように、これを同期させるのに問題があります。

ここで私が持っているコードは、これまでだ:

CONSUMER

do 
{ 
    pthread_mutex_lock(&mutex); 
    pthread_cond_wait(&consumer, &mutex); 

     /*Do some stuff*/ 

    pthread_mutex_unlock(&mutex); 
    count++; 
} while(count < m); /*Where m is the number of producers*/ 

PRODUCER - 各プロデューサーが一つの値だけ(必須 - 割り当て)を生成

pthread_mutex_lock(&mutex); 

    /*Do some stuff*/ 

pthread_cond_signal(&consumer); 
pthread_mutex_unlock(&mutex); 

がそれです条件とmutexだけでこれを行うことは可能ですか?そうでない場合は、セマフォを追加すると簡単になりますが、むしろ試してみることにします。

各プロデューサは、消費者がアクセスする必要があるグローバル変数に製品を配置する必要があります。

他に必要なものがある場合は、お知らせください。

SOLUTION :ジョン・ボリンジャーの回答を読んだ後、私は私の問題を解決し、作業プロデューサ/コンシューマの問題を作成することができました。

/******************CONSUMER*****************/ 
pthread_mutex_lock(&mutex); 
while(count < m) /*While there are more threads*/ 
{ 
    /*Makes producers wait for the consumer to be ready before 
    altering the global variable*/ 
    if(predicate = -1) 
    { 
     predicate = 0; 
     pthread_cond_signal(&producer); 
    } 
    /*Make consumer wait for the global variable to be altered*/ 
    while(predicate == 0) 
     pthread_cond_wait(&consumer, &mutex); 

     /*Do some stuff with global variable*/ 
     predicate = 0; /*Consumed*/ 

    count++; 
    /*Tell a producer that the predicate has been consumed*/ 
    pthread_cond_signal(&producer); 
} 
pthread_mutex_unlock(&mutex); 


/********************PRODUCER********************/ 
pthread_mutex_lock(&mutex); 

/*If the consumer is not ready yet, wait. I.e. if it's still 
    creating more threads*/ 
if(predicate == -1) 
{ 
    pthread_cond_wait(&producer, &mutex); 
} 

/*If there is already a product to be consumed, wait until 
*consumed*/ 
while(predicate != 0) 
{ 
    pthread_cond_wait(&producer, &mutex); 
} 

    /*Do some stuff with global variable*/ 

/*Tell consumer that a product is ready to be consumed*/ 
pthread_cond_signal(&consumer); 
pthread_mutex_unlock(&mutex); 
+0

すべての子(コンシューマ)スレッドが並行して実行され、親(プロデューサ)スレッドが結果を収集するだけであれば、それらを1つずつ「pthread_join」できます。とにかくこれを行うべきでしょう。 – Useless

+0

@Useless今私は正しい方向に向いてくれてありがとうございました。 – MichaelDawn

+0

@Useless、私は 'EDIT1'の下に少しの情報を追加しました。なぜなら、プロデューサが結果にアクセスする方法があるから、pthread_joinを使うことはできないと思いますか? – MichaelDawn

答えて

1

それが唯一の条件とミューテックスでこれを行うことは可能ですか?

他の同期オブジェクトを使用しないことを意味すると仮定すると、まったく他のもの(変数など)ではなく、可能です。 1つのミューテックスと1つの条件変数で行うことができます。この場合、コンシューマ用とコンシューマ用の2つのCVを使用することを検討することができます。

条件変数を正しく使用するには、常に述語が真になるのを待つことを忘れないでください。述語はCV自体の外部にあり、テストするのはプログラマの責任です。条件変数で待機中の標準的なパターンは、このように書きます:

  1. は述語が真であるならば、述語
  2. が、その後CV
  3. に(6)
  4. 待ちに行くミューテックス
  5. テストをロック待機から戻った時に
  6. に行く(2)
  7. [オプション]
  8. はmutexをロック解除ミューテックスの保護の下でものを行う

待機する前に述語をテストする必要があります。待機から復帰した後、再度テストする必要があります(また、再び待機する必要があります)。

あなたのケースでは、プロデューサスレッドの述語は、言い換えれば、「製品を記録するためのグローバル変数が私に利用可能です」ということです。コンシューマー・スレッドの述部は、「グローバル変数で使用可能な製品があります」です。製品の性質とタイプによっては、スレッドがそれらの述部の状態を伝えるための補助変数を追加する必要があるかもしれません。

このようなシステムの1つのスレッドが独自の作業を終了すると、そのスレッドがグローバル状態を適切に更新し、条件変数を通知して他のスレッドが処理を進めることが不可欠であることにも注意してください。これは、上記のステップ(6)の一部として起こるかもしれません。あるいは、あるスレッドがミューテックスを再びロックして、共有状態を更新してCVを通知するかもしれません。

+0

よかったので、私はあなたのおかげでそれをやる方法を見つけ出すことができました。なぜ私はそれが動作するのか理解できるように、私にコードを与えるだけではないことに感謝します。 – MichaelDawn

関連する問題