【问题标题】:multi-threaded consumer,producer C code, not performing?多线程消费者,生产者C代码,不执行?
【发布时间】:2012-02-02 00:50:33
【问题描述】:

我正在尝试做一个简单的多线程消费者/生产者,其中多个读取器和写入器线程从文件读取到缓冲区,然后从缓冲区读取回文件。它应该是线程安全的。但是,它并没有像我预期的那样表现。它在中途停止,但每次都在不同的线路上? 请帮助我理解我做错了什么?!?

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

欢迎提出任何建议!

【问题讨论】:

  • 能否请您更新一下您所做的更改,因为我正在查看类似的问题。

标签: c multithreading mutex consumer producer


【解决方案1】:

我不确定我的回答是否会对您有所帮助.. 但我会尽力为您提供一些参考代码。

我写了一个类似的程序(除了它不写入文件,而是在stdout 中显示队列-/生产-/消耗-项目)。可以在这里找到 - https://github.com/sangeeths/pc。我已将命令行处理和队列逻辑分离到单独的文件中。

希望这会有所帮助!

【讨论】:

  • 我使用了你的代码中的队列实现,因为它更容易添加和删除项目,谢谢!
  • @user1127217 很高兴您可以重用我的一些代码。如果您觉得它有用,请随时投票并选择它作为答案。还请分享您的代码,以便我可以查看并了解它与我的不同之处。谢谢!
【解决方案2】:

除了 Scott Hunter 指出的问题之外,您的读者和作者在持有互斥锁的同时完成所有“真正的工作”,从而打破了拥有多个线程的观点。

阅读器操作如下:

1) 获取互斥锁。
2) 阻塞条件变量,直到工作可用。
3) 从队列中删除工作,可能是信号条件变量。
4) 释放互斥锁。
5) 处理工作。
6) 转到步骤 1。

编写器应按如下方式操作:

1) 获取我们需要写入的信息。
2) 获取互斥锁。
3) 阻塞条件变量,直到队列中有空间。
4) 将信息放入队列,可能是信号条件变量。
5) 释放互斥锁。
6) 转到步骤 1。

注意到两个线程都在不持有互斥锁的情况下做“真正的工作”吗?否则,如果一次只有一个线程可以工作,为什么还要有多个线程呢?

【讨论】:

  • 因为那是竞争条件?或者你是说获取互斥锁是不必要的,b/c cond_wait 为你做的? -- 没关系(我将“应该操作”列表读作“操作”:)
  • 谢谢,这真的很有帮助!我采纳了你的建议,现在效果好多了。
【解决方案3】:

您的线程正在读取和写入您在 main 中打开和关闭的文件。但是 main 在关闭这些文件之前并没有明确地等待线程完成。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-24
    • 2017-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多