2012-12-02 89 views
1

背景信息: 我正在嘗試創建一個C程序,它允許我通過幾個不同的文件(源文件中的2個)搜索最大的素數。該程序是多線程的,以加快進程。在這個程序中,我更喜歡計算時間,而不是浪費時間,讓線程等待,直到所有線程都分配了globalLargestPrime。稍微複雜的線程同步

問題: 我相信在我的程序的某個地方,要麼id沒有被正確地作爲參數傳遞,要麼就是我的程序捱餓了其中一個線程。

奇怪的部分: 當我運行我的程序時,它將運行並完成,但有時它只會產生一個線程,因此它不會搜索兩個文本文件。而其他時候,將產生兩個線程,並從兩個文本文件

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

pthread_mutex_t mutex; 
pthread_cond_t monitor[2]; 
int globalLargestPrime = 0; 
const int numThreads = 2; 
FILE *fIN[2]; 

typedef enum{ 
    FREE, 
    IN_USE 
}lrgstPrm; 
lrgstPrm monLargestPrime;//create struct 

int timed(){ 
return time(NULL); 
} 

int ChkPrim(int n){ 
    int i; 
    int isPrime = 0; 
    int root = sqrt(n); 
    for(i=2; i<root; i++){ 
     if(n % i == 0) 
      isPrime = 1; 
     else 
      isPrime = 0; 
    } 
    return isPrime; 
} 

void *calc_sqrt(void *threadID){//Create Threads 
    int index, currentNum; 
    int localLargestPrime = 0; 
    int id = *(int *)threadID; 
    int thousandsOfTimes = 0; 
    //FILE *fIN = fopen("data.txt", "r"); 

    //printf(PTHREAD_MUTEX_ERRORCHECK); 
    //Calculate some sqrts 
    while(!feof(fIN[id])){ 
    for(index = 0; index < 1000; index++) 
    {//Check every thousand times 
    fscanf(fIN[id], "%d\n", &currentNum); 
    if(currentNum>localLargestPrime) 
     if(ChkPrim(currentNum) == 1) 
     localLargestPrime = currentNum; 
    } 

    pthread_mutex_lock(&mutex); 

    thousandsOfTimes++; 

    while(monLargestPrime == IN_USE) 
    pthread_cond_wait(&monitor[id], &mutex);//wait untill mutex is unlocked 
    monLargestPrime = IN_USE; 
    //Critical Zone 
    printf("Entering Critical Zone My ID: %d\n",id); 
    if(localLargestPrime > globalLargestPrime)//Check for largest num 
     globalLargestPrime = localLargestPrime; 
    else 
     localLargestPrime = globalLargestPrime; 

    for(index = 0; index < numThreads; index++) 
     if(index != id) 
     pthread_cond_signal(&monitor[id]);//signal all threads that mutex is unlocked 
    monLargestPrime = FREE; 
    printf("Exiting Critical Zone My ID: %d\n",id); 
    pthread_mutex_unlock(&mutex); 
// printf("done searching thousand times %d My ID: %d\n",thousandsOfTimes, id); 
    } 
} 

void createText(){ 
    FILE *fOUT = fopen("data.txt", "w"); 
    int i; 
    srand(time(NULL)); 
    for(i=0; i<10000; i++) 
    fprintf(fOUT, "%d\n",rand()%5000); 
    fclose(fOUT); 
} 


int main(){ 
    printf("This is before creating threads\n"); 
    int index, timeDiff; 
    pthread_t threads[2]; 
    pthread_mutex_init(&mutex, NULL); 
    for(index = 0; index < numThreads; index++) 
    pthread_cond_init(&monitor[index], NULL); 
    fIN[0] = fopen("data0.txt","r"); 
    fIN[1] = fopen("data1.txt","r"); 

    timeDiff = time(NULL); 
    //createText(); 

    for(index = 0; index < numThreads; index++){ 
    //int *id = malloc(1); 
    //*id = index; 
    pthread_create(&threads[index],NULL,calc_sqrt,&index); 
    } 
    for(index = 0; index < numThreads; index++) 
    pthread_join(threads[index],NULL); 
    printf("This is after creating threads"); 

    timeDiff = timed() - timeDiff; 

    /*Destroy the mutexes & conditional signals*/ 
    pthread_mutex_destroy(&mutex); 
    pthread_cond_destroy(&monitor[0]); 
    pthread_cond_destroy(&monitor[1]); 


printf("This is the Time %d\n", timeDiff); 
printf("This is the Largest Prime Number: %d", globalLargestPrime); 
return 0; 
} 

閱讀如果有人能告訴我它可以理解這個問題的一些見解

感謝

回答

3

您正在將相同局部變量的地址傳遞給線程。由於該變量爲每個線程更新的創建,當一個線程啓動時,它可能會讀取的目標用戶不同的線程的值:

pthread_create(&threads[index],NULL,calc_sqrt,&index) 
               ^^^^^^ 

什麼你會最終是多個線程使用相同的FILE*閱讀。

既然你傳遞一個簡單的詮釋,你可以直接通過該值作爲線程參數:

pthread_create(&threads[index],NULL,calc_sqrt,(void*)index) 

然後在線程中獲得的價值,像這樣:

int id = (int)threadID; 

有沒有在你的代碼中需要使用條件變量(雖然再次 - 我不確定它是否會導致問題)。您的條件變量跟蹤globalLargestPrime是否正在被另一個線程使用。巧合的是,互斥體也是一樣的!嘗試:

pthread_mutex_lock(&mutex); 

thousandsOfTimes++;  // not sure why this local variable even exists, 
         // much less is in a critical section 

//Critical Zone 
printf("Entering Critical Zone My ID: %d\n",id); 
if(localLargestPrime > globalLargestPrime)//Check for largest num 
    globalLargestPrime = localLargestPrime; 
else 
    localLargestPrime = globalLargestPrime; // again, not sure why this is here... 

printf("Exiting Critical Zone My ID: %d\n",id); 
pthread_mutex_unlock(&mutex); 

而且,您的代碼使用檢查EOF的反模式讀取文件之前:

while (!feof(somefile)) { 
    // whatever... 
} 

這是不對的,但我想可能是在這種情況下一個無害的錯誤。請參閱:

+0

謝謝,它的工作。我覺得這將是一個簡單的錯誤。非常感謝! – Kevin

1

對於初學者來說,你是malloc只有一個字節,並將其分配給一個int *。你應該是malloc'ing sizeof(int)。

另外,如果每個線程都會在自己的文件中找到最大的素數,那麼當每個線程完成時,將取這些結果的最大值。沒有必要通過這種方式在線程之間進行任何同步。

+0

這應該是一個評論不是答案 –