2011-12-10 38 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