2012-12-02 52 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

这应该是一个评论不是答案 –