2011-12-10 56 views
0

我無法讓我的工作線程和輔助線程正確同步。我試圖解決的問題是使用多達10個線程來查找最大的素數10個文件。 1線程是單線程的,大於此值的線程是多線程的。問題在於工作人員向協助人發出信號,表示已找到新的素數。如果數字不重要,輔導員可以忽略它,或者如果重要的話,發出信號更新所有線程my_latest_lgprime。我一直陷在我的大腦和代碼中。工作線程和控制器線程同步

該任務必須使用輔導員和同步來完成。

這是我到目前爲止有:

工人:

void* worker(void* args){ 
    w_pack* package = (w_pack*) args; 
    int i, num; 
    char text_num[30]; 
    *(package->fac_prime) = 0; 
    for(i = 0; i<package->file_count; i++){ 
      int count = 1000000; //integers per file 
      FILE* f = package->assigned_files[i]; 
      while(count != 0){ 
       fscanf(f, "%s", text_num); 
       num = atoi(text_num); 
       pthread_mutex_lock(&lock2); 
       while(update_ready != 0){ 
        pthread_cond_wait(&waiter, &lock2); 
        package->my_latest_lgprime = largest_prime;//largest_prime is global 
        update_ready = 0; 
       } 
       pthread_mutex_unlock(&lock2); 
       if(num > (package->my_latest_lgprime+100)){ 
        if(isPrime(num)==1){ 
         *(package->fac_prime) = num; 
         package->my_latest_lgprime = num; 
         pthread_mutex_lock(&lock); 
         update_check = 1; 
         pthread_mutex_unlock(&lock); 
         pthread_cond_signal(&updater); 
        } 

       } 
       count--; 
      } 
    } 

    done++; 
    return (void*)package; 
}` 

主持人:

void* facilitator(void* args){ 
    int i, temp_large; 
    f_pack* package = (f_pack*) args; 

    while(done != package->threads){ 
      pthread_mutex_lock(&lock); 
      while(update_check == 0) 
       pthread_cond_wait(&updater, &lock); 
      temp_large = isLargest(package->threads_largest, package->threads); 
      if(temp_large > largest_prime){ 
       pthread_mutex_lock(&lock2); 
       update_ready = 1; 
       largest_prime = temp_large; 
       pthread_mutex_unlock(&lock2); 
       pthread_cond_broadcast(&waiter); 
       printf("New large prime: %d\n", largest_prime); 
      } 
      update_check = 0; 
      pthread_mutex_unlock(&lock); 
    } 
} 

這裏的工人包

typedef struct worker_package{ 
    int my_latest_lgprime; 
    int file_count; 
    int* fac_prime; 
    FILE* assigned_files[5]; 
} w_pack; 

如果任何人有任何想法我怎麼能解決這個問題是問題,或者如果使用信號量更簡單的方法,那麼我會很感激這個幫助。

感謝

回答

1

我真的不能當場肯定有問題,但只是簡單地通過閱讀代碼似乎done變量跨線程共享然而,這是訪問和修改不同步。

無論如何,我可以提出一些想法來改進您的解決方案。

  1. 您在啓動時將文件列表分配給每個線程。這不是最有效的方式,因爲處理每個文件可能需要更多或更少的時間。在我看來,更好的方法是獲得單個文件列表,然後每個線程選取列表中的下一個文件。

  2. 你真的需要一個輔導員任務嗎?在我看來,每個線程都可以跟蹤自己的最大素數,並且每次發現新的最大值時,都可以檢查全局最大值並在必要時更新它。您也可以保持一個最大值(不是每個線程的最大值),但是每次需要比較時都需要鎖定。

這裏是我會怎麼寫工作線程的僞代碼:

while (true) { 
    lock(file_list_mutex) 
    if file list is empty { 
     break // we are done! 
    } 
    file = get_next_file_in_list 
    unlock(file_list_mutex) 

    max = 0 
    foreach number in file { 
     if number is prime and number > max { 
      lock(max_number_mutex) 
      if (number > max_global_number) { 
       max_global_number = number 
      } 
      max = max_global_number 
      unlock(max_number_mutex) 
     } 
    } 
} 

開始之前,你需要初始化max_global_number = 0工作線程。

上述解決方案的優點是它不會像您的情況那樣濫用鎖定,因此線程爭用被最小化。

+0

感謝米格爾的迴應。協調者的目的是讓一個線程可以跳過另一個線程可能找到的較小的數字。它應該讓事情更有效率,但在我的實施中,我似乎無法弄清楚如何。至於文件分配,我並不是真的想在這方面更有效率,只有在線程正在運行時。換句話說,我將在分配文件後開始計時。 –

+0

嗨特雷弗。我仍然沒有看到需要一個協調員的任務。請注意,您的解決方案會花費大量的時間等待鎖定或條件,即使它不是素數,也可以針對每個數字執行此操作。有10個線程會產生很多爭用。你並不是真的讓這個過程更有效率,相反。在我的解決方案中,線程以自己的最大值工作,一旦找到一個就會鎖定。而且從那時起,它就會獲得全局最大值,就像你的解決方案一樣。 # – Miguel

+0

+1。我也沒有真正看到調解人的意思,Trevor。您可以輕鬆地讓每個工作人員在發佈新素數時發現並找到更高的值。對於這個問題,你可以先對文件進行排序並減少。一旦找到最大的素數,你就完成了該文件。 – Duck