2015-03-13 245 views
1

我回到使用pthreads和pthread_join的定义困扰我。多次调用pthread_join如何工作?

它说

“的在pthread_join(),直到目标线程终止函数应暂停调用 线程的执行,除非目标线程 已经终止。从成功的在pthread_join()返回 调用时使用非NULL的value_ptr参数,由终止线程传递给 pthread_exit()的值应在 中由value_ptr引用的位置可用。当pthread_join()成功返回 时,目标线程已终止。结果为 多个同时调用pthread_join()指定相同的目标线程 未定义。如果线程调用pthread_join()是 取消,则目标线程不得超脱。”

我想了解,如果我叫在pthread_join一个线程,然后调用pthread_join完成启动第二个线程,两个线程都会启动,即使我想象中,第二个pthread_join也不能被调用,因为第一个连接暂停了主线程的执行,并且运行下一行,直到pthread_exit从被连接的线程中调用。

In特别是,我想,第一个pthread_join必须等到指定的线程调用pthread_exit后,才会继续执行。但事实并非如此,因为我可以这样做:

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

int avail = 0; 

void *consumer(void *unused) 
{ 
    while (1) { 
     if (avail > 0) { 
      --avail; 
      puts("consumed"); 
     } 
    } 
} 

void *producer(void *unused) 
{ 
    while (1) { 
     ++avail; 
     puts("produced"); 
    } 
} 

int main(int argc, char **argv) 
{ 
    pthread_t c_thread; 
    pthread_t p_thread; 
    pthread_create(&c_thread, 0, consumer, 0); 
    pthread_create(&p_thread, 0, producer, 0); 
    pthread_join(c_thread, 0); 
    pthread_join(p_thread, 0); 

    return 0; 
} 

忽略可能的竞争条件的问题,以尽量减少代码大小,为什么都是工作,尽管线程先加入暂停主线程(因此,防止下一个被称为加入,在我心中)。

我真的很想知道这是如何工作的。

提前致谢。

+2

“我为一个线程调用pthread_join,然后调用pthread_join创建第二个线程” - ''pthread_join()'不创建线程。也就是说,你的“问题”缺乏对你所看到的和你期望看到的东西的精确描述。还要注意,你对你所看到的内容的解释不如你实际看到的重要。 – 2015-03-13 18:48:06

+1

您可以添加一个睡眠呼叫或调用'scanf()'等待输入或设置断点。调度程序在创建后不会立即切换到其他线程。也就是说,你可以很容易地检查第二个'pthread_join()'是否被调用,或者至少如果第一个返回。 – 2015-03-13 18:59:29

+0

好吧,这是有道理的,所以联接基本上是一个非繁忙的等待线程在程序恢复之前完成。线程确实由pthread_create创建并启动,但需要时间才能真正运行,因为如果没有告诉等待任何事情,main将会提前退出。 – Dmitry 2015-03-13 19:01:51

回答

5

线程同时运行,在致电pthread_create期间或之后的某个时间开始。调用pthread_join与启动或运行线程无关,只是等到它退出。你的线程已经在运行,并且在第一次加入的时候仍然可以运行,并且它们将继续运行。唯一被第一个连接阻塞的是你的主线程。

+0

你说得对,我看到的是,如果我删除了连接,程序就提前退出,因为它没有在任何线程上等待完成。如果我使用while循环(1){}“而不是连接”,则线程仍会运行。谢谢! – Dmitry 2015-03-13 18:58:17

+0

当'main'返回时程序终止。 (我相信标准说从main返回相当于调用'exit')这包括终止所有线程。线程目前可能运行也可能不运行,这取决于线程的计划运行方式,这取决于您的平台。 – 2015-03-13 19:00:27

0

线程不是在pthread_join中开始,而是在pthread_create中开始。我误以为pthread_join被用来实际启动线程,而在主线程继续执行之前它是一个非繁忙的等待特定线程返回,在我的情况下,主线程返回之前线程有机会致电puts函数。

我的代码中的第二个pthread_join从来没有实际调用,因为main实际上是从第一个等待c_thread返回的pthread_join挂起的。在这个特定场景中的第二次连接是“无操作”,并且程序从未实际得到它,因为消费者从未实际返回。