c - Pthread 条件语句

标签 c multithreading pthreads

如果需要,我可以发布我的代码,但我的问题主要是概念性的。我正在使用线程实现高斯消除。我有 p 个 pthreads 按列主要顺序在 nxn 矩阵上运行。在任何 p 线程开始对列进行操作之前,必须执行行操作以将该列中具有最大值的行移动到对角线。所以我需要每个线程等待然后一致操作。目前,在每一列,每个线程都会检查其 id,id=0 的线程将执行行操作。我的问题是如何让除 id=0 之外的所有线程等待然后统一操作。

我尝试过使用互斥锁和条件。这些似乎不起作用,因为它们将所有访问权限授予单个线程。据我了解,只能以这种方式阻塞线程,方法是让线程请求已经存在的锁,因此它必须等待。在我的例子中,这将是一个问题,因为我不希望任何非 0 线程拥有锁,一旦它们被解锁,我希望它们能够自由操作,直到它们完成列上的工作。

我试图通过简单地将全局“colReady”变量设置为 0 来避免互斥锁。非零线程 while 循环直到 colReady = True。从逻辑上讲,这是完全有道理的,但它并没有以编程方式工作。

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

#define n 20
#define numThr 3

double **matrix;
int pivotReady[n] = { 0 };

pthread_cond_t cond_pivot_ready;
pthread_mutex_t cond_mutex;

int swapRows (int row1, int row2)
{
    double *tempRow = matrix[row1];
    matrix[row1] = matrix[row2];
    matrix[row2] = tempRow;
    return 0;
}

void randinit ()
{
    int i, j;
    for (i = 0; i < n; i++) {
        for (j = 0; j < n + 1; j++) {
            matrix[i][j] = drand48 ();
        }
    }
}

void rowReduce (void *arg);

void printMatrix ()
{
    int i, j;
    for (i = 0; i < n; i++) {
        for (j = 0; j < n + 1; j++) {
            printf (" %4.2f ", matrix[i][j]);
        }
        printf ("\n");
    }
}

int main ()
{
    pthread_cond_init (&cond_pivot_ready, NULL);
    pthread_mutex_init (&cond_mutex, NULL);

    int i, j;
    double temp;
    pthread_t p_threads[numThr];
    pthread_attr_t attr;
    pthread_attr_init (&attr);

    //create matrix
    matrix = malloc (sizeof (double *) * n);
    for (i = 0; i < n; i++) {
        *(matrix + i) = malloc (sizeof (double) * (n + 1));
    }

    randinit ();

    for (i = 0; i < numThr; i++) {
        pthread_create (&p_threads[i], &attr, rowReduce, (void *) ((long) i));
    }

    for (i = 0; i < numThr; i++) {
        pthread_join (p_threads[i], NULL);
    }
    printf ("Final Matrix:\n");
    printMatrix ();

    return 0;
}

void rowReduce (void *arg)
{
    int id = (int) arg;
    int i, pivot, row;
    double ratio, temp, max;
    int maxRow;

    for (pivot = 0; pivot < n - 1; pivot++) {

        //PIVOT THREAD
        if (id == 0) {
            pthread_mutex_lock (&cond_mutex);
            max = matrix[pivot][pivot]
                maxRow = pivot;
            for (i = pivot + 1; i < n; i++) {
                temp = matrix[i][pivot];
                if (temp > max) {
                    max = temp;
                    maxRow = i;
                }
            }
            swapRows (pivot, maxRow);

            pivotReady[pivot] = 1;
            pthread_cond_signal (&cond_pivot_ready);

            for (row = pivot + 1 + id; row < n; row += numThr) {

                ratio = matrix[row][pivot] / matrix[pivot][pivot];
                printf ("t1: row = %d, piv = %d, ratio = %f\n", row, pivot,
                        ratio);
                for (int i = pivot; i < n + 1; i++) {
                    matrix[row][i] -= ratio * matrix[pivot][i];
                }
            }
            pthread_mutex_unlock (&cond_mutex);
        }
        //NON-PIVOT THREAD
        else {
            pthread_mutex_lock (&cond_mutex);
            while (!(pivotReady[pivot])) {
                pthread_cond_wait (&cond_pivot_ready, &cond_mutex);
            }

            for (row = pivot + 1 + id; row < n; row += numThr) {
                ratio = matrix[row][pivot] / matrix[pivot][pivot];
                for (int i = pivot; i < n + 1; i++) {
                    matrix[row][i] -= ratio * matrix[pivot][i];
                }
            }
            pthread_mutex_unlock (&cond_mutex);

        }

    }

    //printf("rowReduce called with id = %d\n", id);
    pthread_exit (0);
}

该程序应该打印一个已采用上三角形式的随机矩阵。

最佳答案

您只需在访问 pivotReady[pivot] 时保持 cond_mutex,因为这是它保护的唯一共享状态。

您还需要使用pthread_cond_broadcast()而不是pthread_cond_signal(),因为您需要所有等待线程在枢轴后继续进行已准备就绪。

经过小幅重构以使行处理代码不再重复后,它看起来像:

for (pivot = 0; pivot < n - 1; pivot++) {

    //PIVOT THREAD
    if (id == 0) {
        max = matrix[pivot][pivot];
        maxRow = pivot;
        for (i = pivot + 1; i < n; i++) {
            temp = matrix[i][pivot];
            if (temp > max) {
                max = temp;
                maxRow = i;
            }
        }
        swapRows (pivot, maxRow);

        pthread_mutex_lock (&cond_mutex);
        pivotReady[pivot] = 1;
        pthread_cond_broadcast (&cond_pivot_ready);
        pthread_mutex_unlock (&cond_mutex);
    }
    //NON-PIVOT THREAD
    else {
        pthread_mutex_lock (&cond_mutex);
        while (!(pivotReady[pivot])) {
            pthread_cond_wait (&cond_pivot_ready, &cond_mutex);
        }
        pthread_mutex_unlock (&cond_mutex);
    }

    for (row = pivot + 1 + id; row < n; row += numThr) {
        ratio = matrix[row][pivot] / matrix[pivot][pivot];
        for (int i = pivot; i < n + 1; i++) {
            matrix[row][i] -= ratio * matrix[pivot][i];
        }
    }
}

关于c - Pthread 条件语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29959170/

相关文章:

c - 由于 sleep() 导致的奇怪行为

c - GCC Atomic Builtins 而不是 pthread?

iOS 将数据库更新移出主线程 - 插入启动 View

c++ - 为什么 Windows 10 在我的程序中启动额外线程?

c++ - 调用 create_pthread() 的 Cast 成员函数

当我使用 AVX 功能时崩溃

c - C中的函数调用

c - 我在哪里可以通过 WinApi 找到消息框的标准系统图标?

c - 线程与进程 : icmp packet creation fails in thread

c - 为什么 typedef 不能与 pthread 一起使用?