在C中打印int指针数组的意外结果

时间:2014-10-14 01:41:22

标签: c arrays multithreading

我有一个简单的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 ...

从这里继续罚款。

1 个答案:

答案 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被设置为前一个线程中的最大值......

要保护“候选人”不会被启动其他线程的代码同时更改(如果这样做),您可以在同步互斥锁(锁定)后获取该变量的副本。但是,说实话,我不确定这个算法是否会让你将这个处理并行化。