3

複数のリーダーとライターのスレッドがファイルからバッファーに読み取り、次にバッファーからファイルに戻す、単純なマルチスレッドのコンシューマー/プロデューサーを実行しようとしています。スレッドセーフである必要があります。ただし、期待どおりに機能していません。途中で止まりますが、毎回別の行で停止しますか? 私が間違っていることを理解するのを手伝ってください?!?

#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;   
}

どんな提案でも大歓迎です!

4

3 に答える 3

3

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

于 2012-01-04T02:59:27.460 に答える
3

Scott Hunter が指摘した問題に加えて、リーダーとライターはミューテックスを保持している間にすべての「実際の作業」を行い、そもそも複数のスレッドを持つという点を無効にします。

リーダーは次のように操作する必要があります。

1) ミューテックスを取得します。
2) 作業が利用可能になるまで条件変数をブロックします。
3) キューから作業を削除します。場合によっては条件変数を通知します。
4) ミューテックスを解放します。
5) 作品を加工します。
6) ステップ 1 に進みます。

ライターは次のように操作する必要があります。

1) 書き込みに必要な情報を取得します。
2) ミューテックスを取得します。
3) キューにスペースができるまで条件変数をブロックします。
4) 情報を待ち行列に入れ、場合によっては条件変数を通知します。
5) ミューテックスを解放します。
6) ステップ 1 に進みます。

両方のスレッドがミューテックスを保持せずに「実際の作業」を行うことに注意してください。そうでなければ、一度に 1 つのみしか機能しないのに、なぜ複数のスレッドを使用するのでしょうか?

于 2012-01-04T03:38:42.467 に答える
0

私の答えがあなたの役に立つかどうかはわかりませんが、参照コードを提供することで最善を尽くします。

同様のプログラムを作成しました (ただし、ファイルに書き込まず、代わりにキュー/生産/消費アイテムを表示しますstdout)。ここで見つけることができます - https://github.com/sangeeths/pc。コマンドライン処理とキュー ロジックを別のファイルに分けました。

お役に立てれば!

于 2012-01-04T05:13:32.373 に答える