【问题标题】:Worker threads and controller thread synchronization工作线程和控制器线程同步
【发布时间】:2012-01-17 12:25:45
【问题描述】:

我无法让我的工作线程和促进线程正确同步。我要解决的问题是使用最多 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;

有没有更简单的方法使用信号量来做到这一点?

【问题讨论】:

    标签: c multithreading synchronization pthreads


    【解决方案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

    上述解决方案的好处是它不会像您的情况那样滥用锁,因此可以最大限度地减少线程争用。

    【讨论】:

    • 感谢米格尔的回复。 facilitator 的目的是使线程可以跳过另一个线程可能找到的小于素数的数字。它应该让事情变得更有效率,但在我的实现中我似乎无法弄清楚如何。至于文件分配,我并没有真正尝试在这方面提高效率,只有在线程运行时。换句话说,我将在分配文件后开始对工人进行计时。
    • 嗨特雷弗。我仍然认为不需要促进者任务。请注意,您的解决方案将花费大量时间等待锁定或条件,您对您查看的每个数字都执行此操作,即使它不是素数。 10个线程会产生很多争用。相反,你并没有真正让这个过程更有效率。在我的解决方案中,线程以其自己的最大值工作,并且只有在找到一个时才会锁定。在那一点上,由于锁定,它还将获取全局最大值,就像在您的解决方案中一样。
    • +1 表示 #2。 Trevor,我也没有真正理解主持人的意思。你可以很容易地让每个工人在发布新的质数并找到已经存在的更高价值时跳过它。就此而言,您可以先对文件进行排序并进行处理。一旦找到最大的素数,您就完成了该文件。
    • @Duck 这些绝对是提高效率的方法,但这里的任务是使用同步和促进者。我想我应该在问题中更清楚地说明这一点。如果你们知道如何使用 cond 变量或信号量进行同步,那就太好了。
    • 你还没有说你当前的实现有什么问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-19
    • 2021-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-20
    相关资源
    最近更新 更多