c - pthreads C 程序在执行时挂起

标签 c parallel-processing pthreads

我正在编写一个程序,在给定 A 和 B 矩阵的情况下执行高斯消去法。我首先获取除数和乘数,创建在 gauss 函数中执行的 pthreads,这些函数在单个“列”上执行它们的操作。然后我调用 main,它生成新的除数和乘数,并通过相同的线程返回进行另一轮操作。使用条件 pthread 变量来完成此操作。

代码挂起,直到我创建一个断点,然后它继续并完成。不确定是什么阻碍了它。需要一些帮助。

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

//Need one mutex variable and two condition variables (one c var for
//communicating between threads, and one c var for communicating with main).
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_cond_t condM = PTHREAD_COND_INITIALIZER;
float arr[3][4] = {{2,-3,1, -22},{7,9,-3, 14},{6,7,2,91}};
float mults[3];
float divisor;
int num_items = 3;

void* gauss(void *mine)
{
    int thread_count=0;
    int x = *((int *)mine);

    for(int i=0;i<num_items;i++)
    {
        /*do something*/
        arr[i][x] = arr[i][x] / divisor;

        for(int k=0;k<num_items;k++){
            if(k!=i)
                arr[k][x] -= mults[k] * arr[i][x];
        }

        /*lock || wait || signal*/
        pthread_mutex_lock(&mut);
        thread_count++;
        if(thread_count < num_items)
            pthread_cond_wait(&cond,&mut);
        else
        {
            pthread_cond_signal(&condM);
            pthread_cond_wait(&cond,&mut);
            thread_count = 0;
        }
        pthread_mutex_unlock(&mut);
    }

    return NULL;
}

int main(int argc, const char * argv[]) {

    int i, j;
    pthread_t threadr[num_items+1];     /*thread id array */
    int is[num_items+1];
    printf("Test");

//    /*input num items*/
//    printf("input the number of items ");
//    scanf("%d",&num_items);
//    
//    /*input A array*/
//    printf("input A array\n");
//    for(i=0;i<num_items;i++)
//        for(j=0;j<num_items;j++)
//            scanf("%f",&arr[i][j]);
//    
//    /*input B array*/
//    printf("input B array\n");
//    for(i=0;i<num_items;i++)
//        scanf("%f",&arr[i][num_items]);

    /*grab first divisor & multipliers*/
    divisor = arr[0][0];
    for(i=0;i<num_items;i++)
    {
        mults[i] = arr[i][0];
    }

    for(i=0;i<num_items+1;i++)
    {
        is[i]=i;
        if(pthread_create(&threadr[i],NULL,gauss,(void *)&is[i]) != 0)
            perror("Pthread_create fails");
    }

    for(i=1;i<num_items;i++)
    {

        pthread_mutex_lock(&mut);
        pthread_cond_wait(&condM,&mut);

        divisor = arr[i][i];
        for(j=0;j<num_items;j++)
        {

            mults[j] = 1;
            if(j != i)
                mults[j] = arr[j][i];
        }
        pthread_cond_broadcast(&cond);
        pthread_mutex_unlock(&mut);
    }

    printf("The X values are:\n");
    for(i=0;i<num_items; i++) {
        printf("%0.3f \n", arr[i][num_items]);
    }

    /*wait for all threads*/
    for(i=0;i<num_items+1; i++)
        if (pthread_join(threadr[i],NULL) != 0)
            perror("Pthread_join fails");

    return 0;
}

最佳答案

你有一个竞争条件(至少一个),你的代码没有正确使用它的条件变量。您可能可以通过修复后者来修复前者。此外,我怀疑您打算共享 gauss() 的局部变量 thread_count,但没有共享没有链接的变量。

首先,竞争条件。考虑主线程:它启动其他三个线程,然后锁定互斥量并等待条件变量 condM 收到信号。但是假设所有线程都设法在主线程开始等待之前发出 condM 信号?条件变量操作是即时的——任何在 main() 等待它之前发生的 condM 信号都会丢失。

现在让我们换个话题来谈谈条件变量。作为the Linux manual for pthread_cond_wait()说:

When using condition variables there is always a Boolean predicate involving shared variables associated with each condition wait that is true if the thread should proceed. Spurious wakeups from the pthread_cond_timedwait() or pthread_cond_wait() functions may occur. Since the return from pthread_cond_timedwait() or pthread_cond_wait() does not imply anything about the value of this predicate, the predicate should be re-evaluated upon such return.

换句话说,条件变量用于在给定条件变为真之前暂停线程操作。用抽象的术语来说,该条件始终是“该线程可以继续进行”,但这是在特定于上下文的术语中实现的。最重要的是,线程从等待中醒来的事实永远不会固有地表明条件为真;它仅仅表示新唤醒的线程应该检查条件是否为真。通常,线程还应在第一次等待之前进行检查,因为条件可能已经为真。

在伪代码中,它看起来像这样:

线程 1:

lock mutex;
loop
    if is_ok_to_proceed then exit loop;
    wait on condition variable;
end loop
// ... maybe do mutex-protected work ...
unlock mutex

线程 2:

lock mutex
    // ... maybe do mutex-protected work ...
    is_ok_to_proceed = true;
    signal condition variable;
unlock mutex

一般来说,在其他地方也有(互斥保护的)代码使 CV 谓词为假,因此有时线程确实会执行它们的等待。

现在考虑如何将其应用于 main() 中的竞争条件。 main() 如何知道是否等待 condM()?某处需要有一个共享变量来回答它,并且它的等待必须以该变量的值为条件。任何允许主线程继续进行的线程都必须为变量和信号 condM 设置适当的值。主线程本身也应该根据需要设置变量,以表明它当时还没有准备好继续。

当然,您的其他 CV 用法也存在同样的问题。

关于c - pthreads C 程序在执行时挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42257101/

相关文章:

c - P 线程 - 从不同大小的整数转换为指针

c - 如何从智能卡获取 universalPrincipalName 对象?

android - 同时调用多个 API 并在相应请求的处理完成后立即更新 UI Android

c++ - 为工作线程任务实现分析器

unix - 在多线程Linux程序中忽略/阻止SIGPIPE信号

C - 即使文件被删除后仍读取文件内容

c++ - C 覆盖 C++ 方法

python - CUDA错误: initialization error when using parallel in python

c - 为什么我的二维结果矩阵数组没有分配到我的大学集群上的所有进程?

具有等待时间的 pthreads 的消费者/生产者