0

pthreads我试图通过使用库来学习如何在 C 中使用线程进行编程。在我的线程函数中,我有一个嵌套的 for 循环:

void* thread_func(void* a) {
    int i, t;
    struct type *b = (struct type*)a;
    int start = b->start;
    int stop = b->stop;
    for(t = 0; t < 1000; t++) {

        for(i = start; i < stop; i++) {
        /* This inner loop is evenly divided among the threads.*/
        /***** Calculation*****/
        }
    }
    return NULL;
}

内层 for 循环中的计算取决于外层 for 循环的前一个 t 步的结果,因此线程必须等待其他线程完成当前 t 步,然后才能继续。有没有办法在继续下一个 t 步之前等待所有线程完成每个 t 步?我尝试使用pthread_join(),但这似乎不是thread_func(). 有人可以指出我正确的方向吗?还是我在尝试一些不可能的事情?

编辑: i 和 t 是thread_func()..forgot 中的局部变量..

EDIT2:也许我的解释不是很清楚......我创建了一些线程main()(代码中未显示)并且每个线程调用thread_func(). 我已经在线程之间划分了内部 for 循环。但是在进行外层for循环中的下一个t-step之前,我应该确保所有线程都已经完成了当前t-step,因为下一个t-step的结果取决于当前t-step的结果。我怎样才能做到这一点?希望现在更有意义..

4

1 回答 1

1

您似乎对线程的一般工作方式有些困惑。

实际上,thread_func()不会在您创建的不同线程之间共享。每个线程都有自己的上下文;即使它们都在执行thread_func(),只要一切都是本地的,它们中的任何一个都不会干扰另一个的计算。

唯一需要担心并发访问的情况是共享数据(例如全局变量)。在这种情况下,您通常使用互斥锁或信号量。阅读pthread_mutex_tsem_t

更新:由于您没有具体说明tand i,我认为它们是局部变量。如果它们是全局的,您必须使用互斥锁来同步访问这些变量。请记住,调用全局变量无意义的名称,例如tori通常是不好的做法。

UPDATE2:通过您的编辑,我现在了解您真正想要什么。目前我能想到的唯一解决方案是你需要一个全局变量来t为每个线程服务。让我们称之为stepstep是全局的,因为每个线程都可以读取它并知道当前迭代是什么。然而,为了协调对这个变量的并发访问,我们需要一个互斥体,正如我之前提到的。

基本布局是这样的:线程存储在其上下文中执行的最后一次迭代。它正在反复测试step以查看它是否被另一个线程更新。发生这种情况时,它开始执行for循环(带有i = start; .... 的循环)在执行循环后,线程必须测试它是否是这次迭代的最后一个;如果是,它必须增加全局step值发生时,任何等待新值的线程step都会向前移动)。

测试我们是否是最后一个线程意味着您以某种方式知道您创建的线程数。您可以将其作为参数传递,或将其定义为常量。我假设它被定义为THREADS_NO.

因此,我们还需要一个全局计数器和互斥锁来知道有多少线程已经结束了当前迭代

因此,您的文件将类似于:

pthread_mutex_t step_mutex;
pthread_mutex_t counter_mutex;

int step;
int counter;

void* thread_func(void* a) {
    int t, i, curr_t;
    struct type *b = (struct type*)a;
    int start = b->start;
    int stop = b->stop;
    t = -1;
    curr_t = 0;
    while (1) {
        while (curr_t == t) {
            /* Wait for the next step */
            pthread_mutex_lock(&step_mutex);
            curr_t = step;
            pthread_mutex_unlock(&step_mutex);      
        }
        /* New value for t arrived */
        t = curr_t;
        if (t >= 1000) {
            break;
        }
        for (i = start; i < stop; i++) {
            /***** Calculation*****/
        }
        pthread_mutex_lock(&counter_mutex);
        if (++counter == THREADS_NO) {
            counter = 0;
            pthread_mutex_lock(&step_mutex);
            step++;
            pthread_mutex_unlock(&step_mutex);
        }
        pthread_mutex_unlock(&counter_mutex);
    }   
    return NULL;
}

您必须在创建任何线程之前初始化两个互斥锁,可能在 中main(),使用:

pthread_mutex_init(&step_mutex, NULL);
pthread_mutex_init(&counter_mutex, NULL);

当你完成工作时,别忘了销毁它们:

pthread_mutex_destroy(&step_mutex);
pthread_mutex_destroy(&counter_mutex);

请注意,您应该测试初始化​​、锁定和销毁互斥锁​​的函数的返回值,因为可能会发生错误。

最后,考虑一下这是否是你真正想要的:也许你需要重新设计你的程序或算法。这种方法效率不高,因为线程会浪费 CPU 周期来重复测试新值step(这称为忙等待)。很像“我们到了吗?我们到了吗?我们到了吗?”......不是很聪明。

注意:我无法测试此代码。您发布的代码使您很难知道您要实现的目标,因此我不确定这是否完全适合您。

于 2013-11-08T16:33:02.367 回答