Pthread条件变量不可预测的结果

时间:2011-07-18 18:39:44

标签: c++ linux g++ pthreads

首先抱歉发布一个很长的问题,但请保持耐心:)。

作为我的应用程序的一部分,我使用线程来读取内存映射文件的不同部分,因为前一半的映射文件由主线程读取和处理,映射文件的后半部分由另一个线程读取和处理。

我正在使用一个条件变量,以确保第二个线程等待,直到主线程填充结构中的文件相关值。

使用这种方法我有时会正确填充文件大小,有时它无法正确显示。

以下是适用的代码:

void * thread_proc(void * arg){

    struct thread_related_data * dat_str = (struct thread_related_data *) arg;

    //pthread_detach(pthread_self());

    pthread_mutex_lock(&(dat_str->mutex));

    while(dat_str->thread_indicator == 0 ){
        pthread_cond_wait(&(dat_str->cond),&(dat_str->mutex));
    }

    if(dat_str->thread_indicator == 1){   // Start data processing

// start processing bottom half of the mapped file and insert data into &dat_str->thread_proc_data

        pthread_mutex_unlock(&(dat_str->mutex));
        printf ("Got conditioned\n");

        int bytes = dat_str->file_size - dat_str->start_bytes; // bytes should have almost half of the length of the file in bytes, but it does not always print the value correctly in the next statement .

        printf(" Bytes :: %d\n", dat_str->start_bytes); // Sometimes this line gets printed twice ..dont know how !!!

        char *start;
        int i = 0;
        while(i <= bytes){
            start = dat_str->file;
            while(*(dat_str->file) != '\n'){
                //printf file++;
            }

            line_proc(start,static_cast(dat_str->file - start - 1),dat_str->phrase);
            dat_str->file++;
            i++;
        }

    }
    return NULL;
}


void inputFile::start_processing(common& com , searchable& phrases){
    pthread_create(&thread1,NULL,thread_proc,&trd);
    //trd.fil_obj = this;
    // Set the char pointer for the thread

    char * temp = file; // pointer to memory mapped file
    temp += file_size/2;
    //cout.setf(std::ios::unitbuf);
    int bytes = temp - file;

    while(*temp != '\n'){
        bytes++;
        temp++;
    }

    if(*temp == '\n'){
        temp++;

        pthread_mutex_lock(&(trd.mutex));
        trd.thread_indicator = 1;         // signalling variable
        trd.file = temp;
        trd.phrase = phrases.text_to_search[0];
        trd.start_bytes = bytes + 1;     // the start pointer of the mapped file
                                                 // for the second thread.
                                                 // i.e second thread will start processing                         from this pointer
        pthread_cond_signal(&(trd.cond));
        pthread_mutex_unlock(&(trd.mutex));

        // Now process half of the file and put the results in record vector

        temp--; // this thread will process upto '\n' first half of the file
         }
}

请让我知道我在哪里犯了逻辑缺陷或者我以错误的方式实现了条件变量。

此外,我已将mutex和条件变量初始化为pthread_mutex_init(&amp;(trd.mutex),NULL)和pthread_cond_init(&amp;(trd.cond),NULL),而不是分别为PTHREAD_MUTEX_INITIALIZER和PTHREAD_COND_INITIALIZER。这会是我问题的原因吗?

谢谢。

2 个答案:

答案 0 :(得分:3)

您对睡眠的条件变量的使用稍微偏离,通常的方法是:

while(!condition)
{
    pthread_cond_wait(...);
}

它处理虚假唤醒(可能发生)的情况。您当前的代码没有检查任何条件,但应该更改为以下内容:

while (dat_str->thread_indicator != 1)
{
    pthread_cond_wait(&(dat_str->cond),&(dat_str->mutex));
}

答案 1 :(得分:2)

可能不是真正的问题。但是你应该小心你不要总是解锁互斥锁

    pthread_mutex_lock(&(dat_str->mutex));

    while(dat_str->thread_indicator == 0 )
    {    pthread_cond_wait(&(dat_str->cond),&(dat_str->mutex));
    }

    if(dat_str->thread_indicator == 1)
    {
        // CODE    

        pthread_mutex_unlock(&(dat_str->mutex));

        // MORE CODE
    }
    // What happens if it is not 1? The lock is still held.

    return NULL

如果文件不包含'\ n'

,会发生什么
while(*temp != '\n') // You may want to test against the last good location.
{
    bytes++;
    temp++;
}