线程和带有依赖项的嵌套for循环(C中的pthreads)

线程和带有依赖项的嵌套for循环(C中的pthreads),c,multithreading,loops,pthreads,nested,C,Multithreading,Loops,Pthreads,Nested,我试图通过使用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

我试图通过使用
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;
}
void*thread\u func(void*a){
int i,t;
结构类型*b=(结构类型*)a;
int start=b->start;
int stop=b->stop;
对于(t=0;t<1000;t++){
对于(i=开始;i<停止;i++){
/*该内环在各螺纹之间均匀分布*/
/*****算计*****/
}
}
返回NULL;
}
内部for循环中的计算取决于外部for循环的前一个t步的结果,因此线程必须等待其他线程完成当前t步,然后才能继续。在继续下一个t步之前,是否有一种方法可以等待所有线程完成每个t步?我试图使用
pthread\u join()
,但在
thread\u func()
中这似乎不起作用。有人能给我指出正确的方向吗?还是我在尝试一些不可能的事情

编辑:i和t是
thread\u func()
中的局部变量。忘了提及这一点


EDIT2:也许我的解释不太清楚。。。我正在
main()
(代码中未显示)中创建一些线程,每个线程调用
thread\u func()
。我已经在线程之间划分了内部for循环。但是在转到外部for循环中的下一个t步之前,我应该确保所有线程都完成了当前t步,因为下一个t步的结果取决于当前t步的结果。我该怎么做?希望这现在更有意义。

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

实际上,
thread\u func()
不会在您创建的不同线程之间共享。每个线程都有自己的上下文;即使它们都在执行
thread\u func()
,也没有一个会干扰另一个的计算,因为一切都是局部的

您必须担心并发访问的唯一情况是共享数据(例如,全局变量)。在这种情况下,通常使用互斥量或信号量。阅读关于
pthread\u mutex\u t
sem\u t

更新:因为您没有指定确切的
t
i
,所以我假设它们是局部变量。如果它们是全局的,则必须使用互斥体来同步对这些变量的访问。请记住,调用全局变量的无意义名称,如
t
i
,通常是不好的做法

更新2:通过您的编辑,我现在明白了您真正想要什么。目前我能想到的唯一解决方案是,您需要一个全局变量,它将充当每个线程的
t
。让我们称之为
步骤
<代码>步骤是全局的,因为每个线程都可以读取它并知道当前迭代是什么。然而,为了协调对这个变量的并发访问,我们需要一个互斥,正如我前面提到的

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

测试我们是否是最后一个线程意味着您知道您创建的线程数。您可以将其作为参数传递,或将其定义为常量。我假设它定义为
threads\u 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;
}
当你完成任务时,别忘了摧毁它们:

pthread_mutex_destroy(&step_mutex);
pthread_mutex_destroy(&counter_mutex);
请注意,您应该测试初始化、锁定和销毁互斥体的函数的返回值,因为可能会发生错误

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


注意:我无法测试此代码。您发布的代码使您更难了解您想要实现的目标,因此我不确定这是否完全适用于您。

您的语句没有太多意义。t和我声明在哪里?也许不必等待线程完成,而是使用pthread semaphores更有用。如果不知道你在做什么,很难说。我猜你想运行外部的“t”循环,然后进一步执行“I”循环。如果你想这样做,你应该在“t”循环中创建“I”循环线程,并在“t”循环的下一次迭代之前等待它们全部完成。描述tive听起来你想要类似于
pthread\u barrier
的东西,但是,从描述上来说,听起来你有更多的设计问题。你不能为兄弟线程调用pthread\u join。当然可以。@Duck很高兴听到这一点,我有一个想法,这是不允许的,不知道为什么。谢谢你提供的信息。我试图在这方面更加具体和清晰我现在的问题。希望有帮助;)无论如何谢谢你的快速回复。@Koen我明白了。我更新了我的答案,我想这是你想要的。虽然效率不高,它使用繁忙的等待,但你做不了什么。也许重新设计你的程序?@FilipeGonçalves谢谢
pthread_mutex_destroy(&step_mutex);
pthread_mutex_destroy(&counter_mutex);