背景资料: 我正在尝试创建一个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", ¤tNum);
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;
}
如果有人能在这个问题上给我一些见解,我们将不胜感激
由于
答案 0 :(得分:3)
您将同一局部变量的地址传递给线程。由于变量在创建每个线程时都会更新,因此当线程启动时,它可能会读取一个用于不同线程的值:
pthread_create(&threads[index],NULL,calc_sqrt,&index)
^^^^^^
您最终将使用相同的FILE*
读取多个线程。
由于您传入的是一个简单的int,因此您可以直接将该值作为线程参数传递:
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...
}
这是错误的,虽然我认为在这种情况下可能是一个无害的错误。参见:
答案 1 :(得分:1)
对于初学者来说,你只需要一个字节,并将其分配给一个int *。你应该是malloc'ing sizeof(int)。
此外,如果每个线程在其自己的文件中找到最大的素数,那么会更简单,然后当每个线程完成时,取这些结果的最大值。没有必要以这种方式在线程之间进行任何同步