使用 pthread 进行锻炼,但我的代码中有一些意外行为

Posted

技术标签:

【中文标题】使用 pthread 进行锻炼,但我的代码中有一些意外行为【英文标题】:Exercising with pthreads but I am having some unexpected behaviours in my code 【发布时间】:2019-05-18 17:13:40 【问题描述】:

我想在 c 中编写一个程序,该程序将使用 pthreads 对数组的平方数求和以实现代码的并行执行,但是在 linux 环境中执行代码时,我得到 分段错误(核心哑)消息。

奇怪的是,当我通过 DevC++ 在 windows 环境中运行完全相同的代码时,代码执行没有问题。

除此之外,似乎只有 1 个线程正在完成工作,导致串行执行。

我不知道我是否错了,但pthread_self() 返回的是相同的 ID。总的来说,我还是 pthreads 和编程的新手,我找不到问题所在,所以我需要你的帮助。

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

void *calculation(int table[], int k);


pthread_mutex_t sum_mutex = PTHREAD_MUTEX_INITIALIZER;
int  n, p, sum = 0;

int main()

    int i, k=0, check, *table;

    printf("Give the number of threads:\n");
    scanf("%d",&p);
    pthread_t threads[p];

    printf("Give the number of elements of the table:");
    do
    printf("The number of elements must be an integral multiple of the number of threads\n");
    scanf("%d",&n);
    check=n%p;
    if(check!=0)
    printf("Jesus how hard is it?\n");
    printf("Try one more time\n");
    printf("Give the number of elements of the table:\n");
    
    while(check!=0);

    table = (int*) malloc(n * sizeof(int));
    if(table == NULL)          
        printf("Error! Memory not allocated.\n");
        exit(0);
    

    printf("Give the elements of the table:\n");
    for(i=0;i<n;i++)
        scanf("%d",&table[i]);
    

    for(i=0;i<p;i++)                                                       //thread creation
        pthread_create(&threads[i], NULL, calculation(table, k), NULL);
        k++;                                                                //k is a variable used to seperate table, explained later
    
    for(i=0;i<p;i++)
        pthread_join(threads[i],NULL);
    

    printf("Sum of vector= %d\n",sum);

    free(table);
    exit(0);
    return 0;


void *calculation(int table[], int k)
    int i;
    int local_sum=0;
    for(i=(n/p)*k;i<(n/p)*(k+1);i++)                                        //this algorithm seperates the table into equivelant pieces and
                                                                           //every pthread is calculating its given piece then stores that value in its local variable sum
        if((n/p)>n)                                                        //then it is updating the global variable
            pthread_exit(NULL);
        
        local_sum+=pow(table[i], 2);
        printf("Thread's %lu calculation is %d\n", pthread_self(), local_sum);
    

    pthread_mutex_lock(&sum_mutex);                                         //mutex used here to protect the critical code
    sum += local_sum;
    pthread_mutex_unlock(&sum_mutex);

如果我没记错的话,一个线程正在运行代码的不同“副本”,因此每个线程的局部变量是不同的。在计算 local_sum 后,它会更新由于明显原因而受到保护的全局总和。

正如我所说,在 Windows 环境中,这段代码运行平稳,但似乎同一个 pthread 正在完成所有工作。相反,工作应该被分成尽可能多的线程。

不要忘记在 linux 环境中核心根本没有运行导致错误:分段错误(核心愚蠢)。

【问题讨论】:

关于:pthread_create(&amp;threads[i], NULL, calculation(table, k), NULL);函数名不能有参数 【参考方案1】:

来自手册页,pthread_create 的声明

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                     void *(*start_routine) (void *), void *arg);

pthread_create 的第三个参数是一个函数指针,它以void* 作为参数。 在您的情况下,您有两个参数void *calculation(int table[], int k);

您将参数传递给pthread_create 的方式也是错误的,它应该只是函数名而不是其参数。(阅读有关回调函数的更多信息)。最后一个NULL 应该是参数。在您的情况下,您想传递 tablek 但它应该是单个指针。

pthread_create(&amp;threads[i], NULL, calculation(table, k), NULL);

下面,我修改了代码并引入了一个新的struct thread_arg,其中包含tablek,这个struct将传递给你的calculation,然后它会解开它并正常使用。

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

struct thread_arg 
        int *table;
        int k;
;

void *calculation(void *);

pthread_mutex_t sum_mutex = PTHREAD_MUTEX_INITIALIZER;
int  n, p, sum = 0;

int main()

        int i, k=0, check, *table;

        printf("Give the number of threads:\n");
        scanf("%d",&p);
        pthread_t threads[p];

        printf("Give the number of elements of the table:");
        do
                printf("The number of elements must be an integral multiple of the number of threads\n");
                scanf("%d",&n);
                check=n%p;
                if(check!=0)
                        printf("Jesus how hard is it?\n");
                        printf("Try one more time\n");
                        printf("Give the number of elements of the table:\n");
                
        while(check!=0);

        table = (int*) malloc(n * sizeof(int));
        if(table == NULL)
                printf("Error! Memory not allocated.\n");
                exit(0);
        

        printf("Give the elements of the table:\n");
        for(i=0;i<n;i++)
                scanf("%d",&table[i]);
        

        // edit: since I know the size allocated memory for th_args;
        struct thread_arg th_args[p];

        for(i=0;i<p;i++)                                                       //thread creation
                th_args[i].table = table;
                th_args[i].k = k;
                pthread_create(&threads[i], NULL, calculation, &th_args[i]);
                k++;                                                                //k is a variable used to seperate table, explained later
        
        for(i=0;i<p;i++)
                pthread_join(threads[i],NULL);
        

        printf("Sum of vector= %d\n",sum);

        free(table);
        exit(0);
        return 0;


void *calculation(void *data)
        int i;
        int local_sum=0;
        int *table;
        int k;

        struct thread_arg *th_args = data;
        k = th_args->k;
        table = th_args->table;

        printf("shubham: thread_spawned\n");
        for(i=(n/p)*k;i<(n/p)*(k+1);i++)                                        //this algorithm seperates the table into equivelant pieces and
                                                                               //every pthread is calculating its given piece then stores that value in its local variable sum
                if((n/p)>n)                                                        //then it is updating the global variable
                        pthread_exit(NULL);
                
                local_sum+=pow(table[i], 2);
                printf("Thread's %lu calculation is %d\n", pthread_self(), local_sum);
        

        pthread_mutex_lock(&sum_mutex);                                         //mutex used here to protect the critical code
        sum += local_sum;
        pthread_mutex_unlock(&sum_mutex);

        // edit: function returs NULL;
        return NULL;

Edit1:现在calculation 返回NULL,通过创建p th_args 处理k++ 情况

【讨论】:

我完全误解了声明,我认为第四个参数是线程本身的参数,我有多傻。这解决了我的代码的第二个问题,即只有一个线程在工作。但一个问题仍然存在。我仍然得到 segmentaion fault (core dumped)。你知道我该如何解决这个问题吗? @ΠαναγιώτηςΓκιώκας 你现在能检查一下吗?我做了一些修改。 @rafix07 谢谢,我实际上忘记为 th_args 分配内存,并没有注意到 k 正在增加。 @rafix07 @Shubham 谢谢你们,这是我问题的解决方案。我很难弄清楚这段代码``` for(i=0;i

我创建了一个长度为p 的数组th_args。在for 循环中,我正在用所需的值填充结构,检查`k` 是否递增。我们将struct thread_arg 的地址传递给calculation

以上是关于使用 pthread 进行锻炼,但我的代码中有一些意外行为的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在没有 pthread_join() 的情况下使用 pthread?

对于某些构建目标,NDK构建器r15既未找到HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC,也未找到pthread_condattr_setclock;构建失败

以非常低的优先级运行线程

我正在构建一个简单的锻炼计划应用程序,但我想简化 Javascript/jQuery 代码

NSOperationQueue 与 pthread 优先级

在 AIX 上使用 pthread 进行静态链接