2012-01-04 9 views
3

私は単純なマルチスレッドコンシューマ/プロデューサをやろうとしています。ここでは、複数のリーダライタスレッドがファイルからバッファに読み込み、次にバッファからファイルに読み込みます。スレッドセーフである必要があります。しかし、それは私が期待どおりに実行されていません。途中で停止しますが、毎回別の回線で停止しますか? 私が間違っていることを理解してもらえますか?マルチスレッドコンシューマ、プロデューサCコード、実行していない?

#include <pthread.h> 
#include <stdio.h> 
#include <stdlib.h> 
//TODO Define global data structures to be used 
#define BUF_SIZE 5 
FILE *fr; 
FILE *to;   /* declare the file pointer */ 

struct _data { 
    pthread_mutex_t mutex; 
    pthread_cond_t cond_read; 
    pthread_cond_t cond_write; 
    int condition; 
    char buffer[BUF_SIZE]; 
    int datainbuffer; 
}dc1 = { 
    PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER,PTHREAD_COND_INITIALIZER,0,{0},0 
}; 


void *reader_thread(void *arg) { 
    //TODO: Define set-up required 
    struct _data *d = (struct _data *)arg; 
    int killreaders = 0; 
    while(1) { 
     //TODO: Define data extraction (queue) and processing 

     pthread_mutex_lock(&d->mutex); 

     while (d->condition == 0 || d->datainbuffer<=0){ 
      pthread_cond_wait(&d->cond_read, &d->mutex); 
      if(killreaders == 1){ 
       pthread_mutex_unlock(&d->mutex); 
       pthread_cond_signal(&d->cond_read); 
       pthread_cond_signal(&d->cond_write); 
       return NULL; 
      } 

     } 
     d->condition = 0; 

     int i; 
     char res; 
     //if the buffer is not full, that means the end of file is reached and it time to kill the threads remaining. 
     if(d->datainbuffer!=BUF_SIZE) 
      killreaders = 1; 

     for (i=0; i<(sizeof d->datainbuffer); i++) { 
      res = d->buffer[i]; 
      printf("to file:%c",res); 
      fputc(res, to); 
     } 
     d->datainbuffer = 0; 


     pthread_mutex_unlock(&d->mutex); 
     pthread_cond_signal(&d->cond_write); 


    } 

    return NULL; 
} 

void *writer_thread(void *arg) { 
    //TODO: Define set-up required 
    struct _data *d = (struct _data *)arg; 
    char * pChar; 
    int killwriters = 0; 

    while(1){ 
     pthread_mutex_lock(&d->mutex); 
     while(d->condition == 1 || d->datainbuffer>0){ 
      pthread_cond_wait(&d->cond_write, &d->mutex); 
      if(killwriters==1){ 
       pthread_mutex_unlock(&d->mutex); 
       pthread_cond_signal(&d->cond_write); 
       pthread_cond_signal(&d->cond_read); 
       return NULL; 

      } 
     } 
     d->condition = 1; 
     int i; 
     char rc; 
     for (i = 0; i < BUF_SIZE; i++){ 
      if((rc = getc(fr)) == EOF){ 
       killwriters = 1; 
       pthread_mutex_unlock(&d->mutex); 
       pthread_cond_signal(&d->cond_read); 

       return NULL; 
      } 
      d->datainbuffer = i+1; 
      d->buffer[i] = rc; 
      printf("%c",rc); 
     } 

     int m = 0; 

     pthread_mutex_unlock(&d->mutex); 
     pthread_cond_signal(&d->cond_read); 


    } 


    return NULL; 
} 


#define M 10 
#define N 20 
int main(int argc, char **argv) { 
    struct _data dc=dc1; 

    fr = fopen ("from.txt", "rt"); /* open the file for reading */ 
    if (fr == NULL) 
    { 
     printf("Could not open file!"); 
     return 1; 
    } 
    to = fopen("to.txt", "wt"); 


    int i; 
    pthread_t readers[N]; 
    pthread_t writers[M]; 


    for(i = 0; i < N; i++) { 
     pthread_create(&readers[i], NULL, reader_thread, (void*)&dc); 
    } 

    for(i = 0; i < M; i++) { 
     pthread_create(&writers[i], NULL, writer_thread, (void*)&dc); 
    } 
    fclose(fr); 
    fclose(to); 

    return 0; 
} 

ご了承ください。

+0

同様の問題を抱えているように私が助けてくれる変更を加えてください。 – m4n07

答えて

3

あなたのスレッドはファイルを読み書きしています。開くファイルは&です。しかし、mainは、それらのファイルを閉じる前にスレッドが終了するのを明示的に待つことはありません。

+0

あなたは正しかった、あなたの助けに感謝! – user1127217

2

Scott Hunterが指摘している問題に加えて、読者と作家はmutexを保持している間にすべての「実際の作業」を行い、最初に複数のスレッドを持つ点を克服します。

1)ミューテックスを取得次のよう

読者が動作しなければなりません。
2)作業が可能になるまで条件変数をブロックします。
3)キューから作業を取り除いてください。おそらくシグナル状態変数です。
4)ミューテックスを解放してください。
5)作業を処理します。

1)私たちが書くために必要な情報を取得します。
6)は次のように動作しなければならない。1.

作家に進みます。
2)ミューテックスを取得します。
3)キューに空白ができるまで条件変数をブロックします。
4)情報をキューに入れます。可能であれば信号条件変数。
5)ミューテックスを解放します。
6)手順1に進みます。

両方のスレッドがミューテックスを保持せずに「実際の作業」を行っていますか?さもなければ、それらのうちの1つだけが一度に仕事をすることができるなら、なぜ複数のスレッドを持つのですか?

+0

それは競争状態がどこにあるのでしょうか?それとも、mutexを取得する必要がないと言っていますか?b/c cond_waitはあなたにそれをしますか? - 決して気にしないでください(私は "操作すべき"というリストを "操作する"と読んでいます:) –

+1

本当に助けてくれてありがとう!私はあなたのアドバイスを取ったし、それは今よりよく実行されます。 – user1127217

0

私の答えがあなたを助けるかどうかはわかりませんが、私はあなたに参考コードを与えることで最善を尽くすつもりです。

私は同様のプログラムを書いています(ただし、ファイルに書き込まず、代わりにstdoutのqueue-/produced-/consumed-項目を表示します)。それはここに見つけることができる - https://github.com/sangeeths/pc。私は、コマンドライン処理とキューロジックを別々のファイルに分けました。

希望すると便利です。

+0

私はあなたのコードからキューの実装を使用しました。 – user1127217

+0

@ user1127217私のコードの一部を再利用できることをうれしく思っています。それが役に立つと分かっているなら、自由にupvoteして答えとしてこれを選択してください。また、コードを共有して、私が見直して、私のものとはどのように違うのかを学ぶことができます。ありがとう! –

関連する問題