稍微复杂的线程同步(Slightly complicated thread synchronizat

2019-10-17 10:47发布

背景信息:我想创建一个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;
}

如果有人能给我对这个问题的一些见解将会理解

谢谢

Answer 1:

你传递在同一个局部变量的线程的地址。 由于该变量为每个线程更新的创建,当一个线程启动时,它可能会读取的目标用户不同的线程的值:

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...
}

这是不对的,但我想可能是在这种情况下一个无害的错误。 看到:

  • 常见的C编程错误:使用FEOF()不正确
  • “而(!FEOF(文件))”总是错的


Answer 2:

对于初学者来说,你malloc'ing只有一个字节,然后将其赋值为int *。 你应该malloc'ing的sizeof(int)的。

此外,它就会简单得多,如果每个线程会发现的最大素在它自己的文件,那么当每个线程完成,把这些结果的最大值。 无感需要这样的线程之间的同步。



文章来源: Slightly complicated thread synchronization