我遇到了让我的工作线程和辅助线程正确同步的问题。我试图解决的问题是使用多达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;
使用信号量有更简单的方法吗?
答案 0 :(得分:1)
我无法确定地发现问题,但只是通过简单地阅读代码,似乎done
变量在线程之间共享,但是在没有同步的情况下访问和修改它。
无论如何,我可以提出一些改进解决方案的想法。
在启动时为每个线程分配文件列表。这不是最有效的方法,因为处理每个文件可能需要更多或更少的时间。在我看来,更好的方法是拥有一个文件列表,然后每个线程选择列表中的下一个文件。
你真的需要一个辅导员任务吗?在我看来,每个线程都可以跟踪它自己的最大素数,每次它找到一个新的最大值时,它可以检查全局最大值并在必要时更新它。您也可以保留一个最大值(不带每个线程最大值),但这需要您在每次需要比较时锁定。
以下是我将如何编写工作线程的伪代码:
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
。
上述解决方案的好处是它不会像您的情况那样滥用锁定,因此最小化了线程争用。