2017-03-06 74 views
1

我在我的程序中使用2個線程,1打印偶數,另一個按順序打印奇數。當我運行下面的代碼時,程序在打印0和1後會阻塞。看起來像是死鎖。
但是,如果我將rc = pthread_mutex_lock(&互斥量)移至PrintEvenNos()和PrintOddNos()中的while語句之上,則輸出是順序且完整的(根據需要)。 有人可以解釋爲什麼它在第一種情況下失敗,什麼導致了僵局?pthread_mutex_lock和pthread_cond_wait/signal導致死鎖

#include<stdio.h> 
#include<pthread.h> 

pthread_t tid[2]; 
unsigned int shared_data = 0; 
pthread_mutex_t mutex; 
pthread_cond_t even,odd; 
unsigned int rc; 

void* PrintEvenNos(void*); 
void* PrintOddNos(void*); 

void main(void) 
{ 
    pthread_create(&tid[0],0,&PrintEvenNos,0); 

    pthread_create(&tid[1],0,&PrintOddNos,0); 
    sleep(3); 

    pthread_join(tid[0],NULL); 
    pthread_join(tid[1],NULL); 
} 

void* PrintEvenNos(void *ptr) 
{ 
    //rc = pthread_mutex_lock(&mutex);  /*works when I uncomment here and comment the next mutex_lock */ 
     while (shared_data <= 5) 
    {rc = pthread_mutex_lock(&mutex); 
     if(shared_data%2 == 0) 
     { printf("t1.....................................Even:%d\n",shared_data); 
     shared_data++; 
     pthread_cond_signal(&odd); 
     rc=pthread_mutex_unlock(&mutex); 
    } 
    else 
    { 
      pthread_cond_wait(&even, &mutex); 
    } 
} 
    rc=pthread_mutex_unlock(&mutex); 
} 

void* PrintOddNos(void* ptr1) 
{ 
// rc = pthread_mutex_lock(&mutex); /*works when I uncomment here and comment the next mutex_lock */ 
    while (shared_data <= 5) 
    { 
    rc = pthread_mutex_lock(&mutex); 
    if(shared_data%2 != 0) 
     { 
     printf("t2.....................................odd:%d\n",shared_data); 
      shared_data++; 
      pthread_cond_signal(&even); 
      rc=pthread_mutex_unlock(&mutex); 
     } 
     else 
      { 
       pthread_cond_wait(&odd, &mutex); 
     } 
    } 
rc=pthread_mutex_unlock(&mutex); 
} 
+1

除了給出的答案,您需要靜態或使用pthread_mutex_init()來初始化您的互斥鎖。 –

+0

是的,也是條件變量。事實上,這裏已經有了一個默認的初始化,因爲這些都是全局變量。但是這通常是不夠的,你需要使用'PTHREAD_MUTEX_INITIALIZER'和'PTHREAD_COND_INITIALIZER'。 –

回答

0

移動鎖定並解鎖,如您在評論中所述。按照放置,你的程序有一個競爭條件,因此未定義的行爲。您無法訪問可能會被另一個線程修改而無需同步的數據,以免排除併發訪問。

1

您的程序存在未定義的行爲,因爲您正在等待的線程在從pthread_cond_wait返回時重新獲得了鎖,然後再次在它已擁有的互斥鎖上調用pthread_mutex_lock

互斥體是用來指明你的評論。這正是pthread_cond_wait所做的:它釋放入口鎖定並在返回時重新獲得鎖定。

另外,從if分支中刪除pthread_mutex_unlock,這是錯誤的。通常,您應該只有一對lock/unlock來電標記您的關鍵部分。