2017-02-15 98 views
1

我正在寫一個程序,執行高斯消除給定一個A和B矩陣。我首先獲取除數和乘數,創建在高斯函數中執行的pthread,它們在一個「列」上執行操作。然後我調用main來生成新的除數和乘數,並通過相同的線程返回進行另一輪操作。使用條件pthread vars來實現這一點。pthreads C程序掛起執行

代碼掛起,直到我創建一個斷點,然後它繼續並完成。不知道是什麼阻止了它。可以使用一些幫助。

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

//Need one mutex variable and two condition variables (one c var for 
//communicating between threads, and one c var for communicating with main). 
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 
pthread_cond_t condM = PTHREAD_COND_INITIALIZER; 
float arr[3][4] = {{2,-3,1, -22},{7,9,-3, 14},{6,7,2,91}}; 
float mults[3]; 
float divisor; 
int num_items = 3; 

void* gauss(void *mine) 
{ 
    int thread_count=0; 
    int x = *((int *)mine); 

    for(int i=0;i<num_items;i++) 
    { 
     /*do something*/ 
     arr[i][x] = arr[i][x]/divisor; 

     for(int k=0;k<num_items;k++){ 
      if(k!=i) 
       arr[k][x] -= mults[k] * arr[i][x]; 
     } 

     /*lock || wait || signal*/ 
     pthread_mutex_lock(&mut); 
     thread_count++; 
     if(thread_count < num_items) 
      pthread_cond_wait(&cond,&mut); 
     else 
     { 
      pthread_cond_signal(&condM); 
      pthread_cond_wait(&cond,&mut); 
      thread_count = 0; 
     } 
     pthread_mutex_unlock(&mut); 
    } 

    return NULL; 
} 

int main(int argc, const char * argv[]) { 

    int i, j; 
    pthread_t threadr[num_items+1];  /*thread id array */ 
    int is[num_items+1]; 
    printf("Test"); 

// /*input num items*/ 
// printf("input the number of items "); 
// scanf("%d",&num_items); 
//  
// /*input A array*/ 
// printf("input A array\n"); 
// for(i=0;i<num_items;i++) 
//  for(j=0;j<num_items;j++) 
//   scanf("%f",&arr[i][j]); 
//  
// /*input B array*/ 
// printf("input B array\n"); 
// for(i=0;i<num_items;i++) 
//  scanf("%f",&arr[i][num_items]); 

    /*grab first divisor & multipliers*/ 
    divisor = arr[0][0]; 
    for(i=0;i<num_items;i++) 
    { 
     mults[i] = arr[i][0]; 
    } 

    for(i=0;i<num_items+1;i++) 
    { 
     is[i]=i; 
     if(pthread_create(&threadr[i],NULL,gauss,(void *)&is[i]) != 0) 
      perror("Pthread_create fails"); 
    } 

    for(i=1;i<num_items;i++) 
    { 

     pthread_mutex_lock(&mut); 
     pthread_cond_wait(&condM,&mut); 

     divisor = arr[i][i]; 
     for(j=0;j<num_items;j++) 
     { 

      mults[j] = 1; 
      if(j != i) 
       mults[j] = arr[j][i]; 
     } 
     pthread_cond_broadcast(&cond); 
     pthread_mutex_unlock(&mut); 
    } 

    printf("The X values are:\n"); 
    for(i=0;i<num_items; i++) { 
     printf("%0.3f \n", arr[i][num_items]); 
    } 

    /*wait for all threads*/ 
    for(i=0;i<num_items+1; i++) 
     if (pthread_join(threadr[i],NULL) != 0) 
      perror("Pthread_join fails"); 

    return 0; 
} 
+0

它沒有解釋掛起,但請注意,無條件地選擇主對角線的元素作爲除數是不安全的。這些可以是零(即使對於非奇異系統),和/或具有使您的方法在數值上不穩定的極端值。 –

+0

對,我正要解決這個問題後懸掛問題。感謝您的答覆。 –

回答

0

您有一個競態條件(至少一個),並且您的代碼沒有正確使用它的條件變量。你可以通過修復後者來修復前者。另外,我懷疑你打算共享gauss()的局部變量thread_count,但沒有鏈接的變量不共享。

首先,比賽條件。考慮主線程:它啓動另外三個線程,然後鎖定互斥鎖,並等待條件變量condM發送信號。但是假設線程在主線程開始等待之前都設法發出信號condM?條件變量操作是立即的 - 在main()等待之前發生的condM的任何信號都將丟失。

現在讓我們換檔討論條件變量。 As the Linux manual for pthread_cond_wait() puts:

當使用條件變量時,總是有一個布爾謂詞涉及與每個條件關聯的共享變量,如果線程應該繼續,則等待爲true。可能會發生pthread_cond_timedwait()pthread_cond_wait()函數的虛假喚醒。由於從pthread_cond_timedwait()pthread_cond_wait()返回並不意味着這個謂詞的價值,所以謂詞應該在這樣的返回時重新評估。

換句話說,條件變量用於掛起線程操作,等待給定的條件變爲真。從抽象的角度來說,這個條件總是「這個線程可以繼續運行」,但是這是以特定的上下文來實現的。最重要的是,線程從等待中醒來的事實從未固有地表明條件是真實的;它只是表示新喚醒的線程應該檢查條件是否爲真。一般來說,線程在第一次等待之前也應該檢查,因爲條件可能已經爲真。

僞代碼,看起來像這樣:

主題1:

lock mutex; 
loop 
    if is_ok_to_proceed then exit loop; 
    wait on condition variable; 
end loop 
// ... maybe do mutex-protected work ... 
unlock mutex 

線程2:

lock mutex 
    // ... maybe do mutex-protected work ... 
    is_ok_to_proceed = true; 
    signal condition variable; 
unlock mutex 

一般來說,也有(互斥保護)代碼別的地方這使得CV謂詞是錯誤的,所以有時線程確實會執行它們的等待。

現在考慮如何適用於main()競賽條件。 main()如何知道是否等待condM()?需要有一個共享變量來回答這個問題,並且它的等待必須以該變量的值爲條件。任何意味着允許主線程繼續運行的線程都必須爲變量設置適當的值並且信號爲condM。主線程本身也應該根據需要設置該變量,以指示在此時準備好而不是

當然,您的其他簡歷使用也會遇到同樣的問題。

+0

謝謝你的幫助。這非常有意義並解決了我的問題。我更好地理解cond_vars。 –