2013-11-10 48 views
0

我有一個簡單的線程程序,它使用一個條件變量和一個rwlock。我一直在盯着它幾個小時嘗試不同的方法。問題是,一段時間之後,一個線程或多個線程停止在rwlock上,儘管它並未鎖定寫入。也許我會錯過關於這些鎖的工作方式或實施方式。有條件變量和rwlock死鎖

#include <stdio.h> 
#include <pthread.h> 
#include <stdlib.h> 
#include <time.h> 
#include <math.h> 
#include <unistd.h> 

//global variables 
pthread_mutex_t mutex; 
pthread_cond_t cond; 
pthread_rwlock_t rwlock; 
int counter; 
int listLength = 1; 

void* worker(void* arg){ 
    do { 
     usleep(200); 
     printf("Before rwlock\n"); 
     pthread_rwlock_rdlock(&rwlock); 
     printf("Before mutex\n"); 
     pthread_mutex_lock(&mutex); 
     printf("Afer mutex\n"); 
     counter++; 
     //signal the main 
     if (counter == 5 || 
       (listLength < 5 && counter == listLength)){ 
      printf("Signal main\n"); 
      pthread_cond_signal(&cond); 
      counter = 0; 
     } 
     pthread_mutex_unlock(&mutex); 
     pthread_rwlock_unlock(&rwlock); 
    } while(listLength != 0); 

    return NULL; 
} 


int main(int argc, char* argv[]){ 
    if (argc != 2){ 
     perror("Invalid number of args"); 
     exit(1); 
    } 
    //get arguments 
    int workers = atoi(argv[1]); 

    //initialize sync vars 
    pthread_rwlockattr_t attr; 
    pthread_rwlockattr_setkind_np(&attr, 
      PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); 
    pthread_mutex_init(&mutex, NULL); 
    pthread_cond_init(&cond, NULL); 
    pthread_rwlock_init(&rwlock, &attr); 
    counter = 0; 

    //create threads 
    pthread_t threadArray[workers]; 
    int threadOrder[workers]; 
    for (int i = 0; i < workers; i++){ 
     threadOrder[i] = i; 
     if (pthread_create(&threadArray[i], NULL, 
        worker, &threadOrder[i]) != 0){ 
      perror("Cannot create thread"); 
      exit(1); 
     } 
    } 

    while(listLength != 0) { 
     //wait for signal and lock the list 
     pthread_mutex_lock(&mutex); 
     while (pthread_cond_wait(&cond, &mutex) != 0); 
     pthread_rwlock_wrlock(&rwlock); 
     printf("In write lock\n"); 

     pthread_mutex_unlock(&mutex); 
     pthread_rwlock_unlock(&rwlock); 
     printf("release wrlock\n"); 
    } 

    //join the threads 
    for (int i = 0; i < workers; i++){ 
     if (pthread_join(threadArray[i], NULL) !=0){ 
      perror("Cannot join thread"); 
      exit(1); 
     } 
    } 

    //release resources 
    pthread_mutex_destroy(&mutex); 
    pthread_cond_destroy(&cond); 
    pthread_rwlock_destroy(&rwlock); 

    return 0; 
} 

回答

1

看起來這個代碼有幾個不一致之處。

  1. 您使用mutexrwlock在一起,這意味着這種所有線程都始終處於鎖定狀態。如果你刪除代碼rwlock - 它不會改變行爲。

  2. 我看不到pthread_rwlock_init()調用,並且假設您在另一個地方調用了它。無論如何要注意你叫它,你不要叫它兩次或更多次與相同的rowlock對象。

    這同樣適用於pthread_rwlockattr_destroy()

  3. 我不明白爲什麼pthread_rwlock_rdlock()會阻止沒有寫鎖的原因。確保你不這樣做。要不然,你可以做你的mutex

+0

工作線程的相互鎖定有一些額外的工作和rwlock的互斥體之間的事,但我把它更容易被發現的問題。如果我拿出rwlock代碼,它不會卡住,但我需要它來做額外的工作。 'pthread_rwlock_init()'在主函數的第一部分。我看不出爲什麼它不應該工作的原因。它只適用於一個工作線程,它會被多個線程阻塞。 – Jelly

+1

我終於解決了這個問題。死鎖是由於當互斥鎖被鎖定時嘗試寫入鎖定引起的,所以所有工作線程都會在主線程在寫鎖時等待互斥鎖並等待互斥鎖。 – Jelly