我有一个简单的C程序,它使用不同数量的pthread来查找前N个素数,添加被发现为数组的素数。该数组作为arg传递给每个线程,每个线程几乎在关键部分执行其所有代码。我对素数检查没有任何问题,并且打印到素数的屏幕和找到它们的result_number变量有效。然而,当找到N个素数并且打印数组时,我发现(大致)程序每执行一次,一些(可变地从1到5)早期素数数组元素(通常限于那些<17)打印出极大或负数,大多数素数打印都很好。只有线程函数的代码在下面(不是checkPrime或main),因为其他所有似乎都能正常工作。
此外,如果程序是用单个线程执行的(即在多个线程之间不共享数组进行更新),这种特性永远不会发生。
result_number,candidate,N都是全局变量。
void *primeNums(void *arg) {
pthread_mutex_lock(&mutex);
int *array = (int *) arg;
int is_prime = 0;
int j = 0;
while (result_number <= N) {
candidate++;
is_prime = checkPrime(candidate);
if (is_prime == 1) {
array[result_number] = candidate;
if (result_number == N) {
while (j < N) {
printf("%d\n", array[j]);
j++;
}
}
/* Test verification output; always accurate */
printf("Result number: %d = %d\n", result_number, candidate);
result_number++;
}
}
pthread_mutex_unlock(&mutex);
}
我真的不相信其他的Q会覆盖这个,就像我看过的那样(并且更愿意找到写我自己的问题的答案)。不可否认,我有可能无法正常搜寻。
编辑:不需要的输出示例: -386877696 3 -395270400 32605 11 13 ...
从这里继续罚款。
答案 0 :(得分:1)
我有一种预感,如果你不是传入数组并使用全局result_number,而是传入array + result_number并循环一个局部变量:i = 0; while(i < N) {...}
,你可以解决你的问题。 (假设array + result_number + N - 1
没有超出范围)。
使用全局变量来保存每个线程的范围信息的问题是线程函数primeNums()
修改了其中的一些。因此,如果您启动第一个线程(线程#1)并将result_number
设置为您希望线程#1处理的范围的开始,则线程#1将在重置它时继续更改其值以提供给线程# 2。因此线程#2不会处理您希望它处理的范围。
我假设您希望每个线程在您的数组中处理单独的索引范围?目前,您正在将指向数组开头的指针传递给函数,并使用全局变量将索引保存到您希望由该线程处理的块的数组中。
要避免使用该全局索引,您只需将指向偏移量的指针传递到要开始处理的数组中间。因此,而不是传入指向开始元素(array
)的值,而不是传递一个值,该值指向要从(array + result_number
)开始处理的元素。
如果你这样做,在你的函数primeNums()
中,它就好像你传入的指针是一个数组的开头(即使它位于中间的某个地方),你可以从{{1 }} 0
因为您在调用函数之前已经添加了N
。
说了所有我怀疑你仍然无法并行处理这个数组(如果那确实是你想要做的),因为每个线程都依赖于result_number
被设置为前一个线程中的最大值......
要保护“候选人”不会被启动其他线程的代码同时更改(如果这样做),您可以在同步互斥锁(锁定)后获取该变量的副本。但是,说实话,我不确定这个算法是否会让你将这个处理并行化。