多线程应用程序

时间:2018-04-11 08:58:46

标签: c multithreading pthreads mutex

我在C中学习多线程,并且有些麻烦理解为什么我的代码没有给出预期的输出和段错误。我在C中使用了pthread库,我的代码启动了总共m * 2个线程,m为它启动的两个函数中的每一个。第一个函数计算30个随机数并将其存储在全局数组中。然后第二个函数从数组中读取整数,计算它们的总和及其平均值。第二个线程也等待第一个带有pthread_join的线程,但它似乎有时会在第一个线程退出之前连接。

我在这里做错了什么?

我也知道使用互斥锁会是一个更好的选择,但我会故意尝试使用互斥锁。

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

int n = 30;
int arr[100][30];

pthread_t tfirst[100];
pthread_t tsecond[100];


void *first(void *x){

    for(int i = 0; i < n; i++)
        arr[(int)x][i] = rand();

}

void *second(void *x){
    pthread_join(tfirst[(int)x], NULL);

    long sum = 0;
    for(int i = 0; i < n; i++){
        sum += arr[(int)x][n];
    }

    printf("Sum %d = %ld\n", (int)x + 1, sum);
    sleep(1);
    printf("Arithmetic mean %d = %f\n", (int)x + 1, (float)sum / n);
}


int main(int argc, char **argv){
    int m;
    srand(time(0));
    if(argc < 2){
        fprintf(stderr, "Usage: %s m [n]", argv[0]);
        exit(EXIT_FAILURE);
    }
    m = atoi(argv[1]);
    if(argc >= 3) n = atoi(argv[2]);


    for(int i = 0; i < m; i++){
        if (pthread_create(&tfirst[i], NULL, first, (void*)i)) {
          fprintf(stderr, "Error creating thread!\n");
          exit(EXIT_FAILURE);
        }

        if (pthread_create(&tsecond[i], NULL, second, (void*)i)) {
          fprintf(stderr, "Error creating thread!\n");
          exit(EXIT_FAILURE);
        }



    }
    for(int i = 0; i < m; i++){
        pthread_join(tfirst[i], NULL);
        pthread_join(tsecond[i], NULL);
    }
    return 0;
}

2 个答案:

答案 0 :(得分:4)

您为同一个帖子调用pthread_join两次 - 首先在second线程例程内,然后在main结尾。

来自pthread_join reference

  

指定同一目标线程的多个同时调用pthread_join()的结果未定义。

     

如果pthread_join()的thread参数指定的值未引用可连接线程,则行为未定义。

部分“如果该线程已经终止,则pthread_join()立即返回”表示在已经结束但仍可加入的线程上调用pthread_join会使调用返回但是,此调用后线程不再可以连接,再次调用pthread_join将导致UB。

你的和计算代码是错误的:sum += arr[(int)x][n];只会使用n值(超出导致UB的界限)。

两个线程例程都应该返回一个值:return NULL;

答案 1 :(得分:1)

  

第二个线程也在等待第一个带有pthread_join的线程,但它似乎有时会在第一个线程退出之前加入。

实际上,第二个线程甚至可以在第一个线程之前开始执行。关于线程执行顺序没有任何保证。

解决方案是仅使用一个线程,即firts()只需调用second()。这将保证这些函数之间的执行顺序,而不需要任何互斥锁。