使用C中的多线程计算序列不能按预期工作

时间:2014-06-14 12:11:31

标签: c multithreading pthreads shared-memory race-condition

我正在尝试用C编写一个计算系列的程序:

for(i=0; i <= n; i++){ (2*i+1)/factorial(2*i); }

n是元素的数量,由用户确定为参数。 用户还确定要计算系列的线程数。

我将子系列划分为仅计算系列的一部分的子系列,每个子系列应由单个线程计算。问题是我的线程可能共享内存,因为一些系列成员计算了很多次而其他系列成员根本没有计算。你知道为什么吗?请帮忙!

以下是代码中有问题的部分:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <gmp.h>
#include <math.h>
#include <pthread.h>

/* a struct to pass function arguments to the thread */
struct intervals_struct {
    int **intervals;
    mpf_t *result;
    int thread_index;
};

/* calculate the sum of the elements of the subseries;
doesn't work properly for more than one thread */
void* sum_subinterval(void *args) {
    /* Initialize the local variables here */

    struct intervals_struct *p = (struct intervals_struct*)args;

    for(i=(*p).intervals[(*p).thread_index][0]; i<=(*p).intervals[(*p).thread_index][1]; i++){
        /* Do something with the local variables here */
    }

    mpf_set((*p).result[(*p).thread_index],sum);

    /* Free resources used by the local variables here */
}

/* calculate the sum of all subseries */     
void main(int argc, char * argv[]){
    int p, t, i;

    p = atoi(argv[1]);
    assert( p >= 0);

    t = atoi(argv[2]);
    assert( t >= 0);

    int **intervals_arr;

    intervals_arr = (int**)malloc(t * sizeof(int *));
    for(i = 0; i < t; i++) {
        intervals_arr[i] = (int *)malloc(2 * sizeof(int));
    }

    /* Calculate intervals and store them in intervals_arr here */

    mpf_t *subinterval_sum;
    subinterval_sum = (mpf_t*)malloc(t * sizeof(mpf_t));
    for(i=0; i < t; i++) {
        mpf_init(subinterval_sum[i]);
    }

    pthread_t *tid;
    tid = (pthread_t *)malloc(t * sizeof(pthread_t));

    for(i = 0; i < t; i++) {
        struct intervals_struct args = {intervals_arr, subinterval_sum, i};
        pthread_create(&(tid[i]), NULL, sum_subinterval, (void*)&args);
    }

    for(i = 0; i < t; i++) {
        pthread_join(tid[i], NULL);
    }

    /* Sum the elements of the result array and free resources used in main here */
}  

1 个答案:

答案 0 :(得分:3)

问题可能在这里:

for(i = 0; i < t; i++) {
    struct intervals_struct args = {intervals_arr, subinterval_sum, i};
    pthread_create(&(tid[i]), NULL, sum_subinterval, (void*)&args);
}

您正在将args的地址传递给新线程,但该变量的生命周期在pthread_create调用后立即结束。编译器可以并且将在不同的循环迭代之间重用args占用的堆栈空间。

尝试使用malloc在堆上分配数组。

编辑:我最后一句话的意思是这样的:

struct intervals_struct * args = (struct intervals_struct *) calloc(t, sizeof(struct intervals_struct));

for(i = 0; i < t; i++) {
    args[i].intervals = intervals_arr;
    args[i].result = subinterval_sum;
    args[i].thread_index = i;
    pthread_create(&(tid[i]), NULL, sum_subinterval, (void*)&args[i]);
}

// at the end of main(), or at least after every thread has been joined
free(args);