2011-07-18 16 views
1

首先抱歉發佈一個長問題,但請保持耐心:)。Pthread條件變量不可預知的結果

作爲我的應用程序的一部分,我使用線程來讀取內存映射文件的不同部分,因爲在映射文件的前半部分被主線程讀取和處理,並且讀取映射文件的後半部分並由另一個線程處理。

我正在使用一個條件變量,以確保第二個線程等待主線程填充結構中的文件相關值。

使用這種方法我有時會正確填充文件大小,有時它不能正確顯示。

這裏是適用的代碼:

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

請讓我知道我在哪裏做了一個邏輯缺陷或有我實現了條件變量以錯誤的方式。

另外,我還分別既互斥和條件變量作爲調用pthread_mutex_init(&(trd.mutex),NULL)和pthread_cond_init(&(trd.cond),NULL)代替PTHREAD_MUTEX_INITIALIZER和PTHREAD_COND_INITIALIZER初始化。這是我的問題的原因嗎?

謝謝。

+0

稍微愚蠢的問題,而是'trd-> thread_indicator'初始化爲0? – Hasturkun

+0

是的,它在類inputFile的構造函數中進行初始化,並且在構造函數本身中,我初始化了互斥鎖和條件變量。 – Arunmu

+0

好的,只是想我會問,因爲使用未初始化的變量會使'cond_wait'被跳過。順便說一句,等待之後的if語句似乎是多餘的(除非你可以傳遞一個不是'1'的值),並且如果沒有輸入就會鎖定互斥鎖。 – Hasturkun

回答

3

您使用的睡眠條件變量的稍微偏離,通常的方法是:

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

此處理雜散喚醒的情況下(這可能發生)。您當前的代碼不檢查任何條件,但也許應該改成類似以下內容:

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

最初我把它放在一個while循環中,我得到了同樣的行爲。我將在這裏編輯代碼,而將其放在裏面,這是通常的做法。 – Arunmu

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++; 
} 
+0

你是對的..在放了一個else之後,我發現有時代碼也會進入else循環!但我只將兩個值分配給線程指示符......但它有時會佔用一些垃圾值,這怎麼可能?但在其他情況下,即使它將線程指示符設置爲「1」,我在線程中出現錯誤的打印。 – Arunmu

+0

這是一個'\ n'分隔的文件。我會一直髮現一個'\ n',因爲這個文件會非常大。 – Arunmu

+0

@ArunMu:永遠不要說永遠(它會咬你的屁股)。就像上面的條件應該一直是'1'。總有一天,事情總會出錯,你需要保護自己脫離無限。 –