【问题标题】:how does calling pthread_join multiple times work?多次调用 pthread_join 是如何工作的?
【发布时间】:2015-03-13 18:43:10
【问题描述】:

我正在重新使用 pthreads,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。

特别是,我想,第一个 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;
}

忽略可能的竞争条件问题以尝试减少代码大小,为什么两个线程都在工作,尽管第一个连接暂停了主线程(因此,在我看来,阻止了下一个连接被调用)。

我真的很想了解它是如何工作的。

提前谢谢。

【问题讨论】:

  • “我为一个线程调用 pthread_join,然后调用 pthread_join 创建第二个线程”——pthread_join() 不创建线程。也就是说,您的“问题”缺乏对您所看到的以及您期望看到的内容的精确描述。另请注意,您对所见事物的解释不如实际所见重要。
  • 您可以添加一个睡眠调用或调用scanf() 等待输入或设置断点。调度程序在创建后不会立即切换到不同的线程。也就是说,您可以轻松检查是否调用了第二个 pthread_join(),或者至少是否调用了第一个。
  • 好吧,这是有道理的,所以连接基本上充当了在程序恢复之前等待线程完成的非忙碌等待。线程确实是由 pthread_create 创建和启动的,但实际运行需要时间,因为如果没有告知 main 等待任何内容,main 将提前退出。
  • "...让线程完成。"不,为了完成线程,特别是您在调用pthread_join 时指定的线程。并且相关线程的用户代码也不必直接调用pthread_exit。它可以简单地return something;(参见this man page 中的项目符号)。不一定对你很重要,但对 C++ 程序员很重要。

标签: c multithreading


【解决方案1】:

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

【讨论】:

  • 你说得对,我看到的是,如果我删除连接,程序会提前退出,因为它根本没有等待任何线程完成。如果我创建一个繁忙的循环而不是连接“while(1) {}”,那么线程无论如何都会运行。谢谢!
  • 程序在main返回时终止。 (我相信标准说从 main 返回相当于调用exit)这包括所有线程的终止。线程此时可能已运行,也可能未运行,这取决于线程如何调度运行,具体取决于您的平台。
【解决方案2】:

线程不在 pthread_join 中启动,而是在 pthread_create 中启动。我误导自己认为 pthread_join 用于实际启动线程,而在主线程继续执行之前,它是等待特定线程返回的非忙碌等待,在我的情况下,主线程在线程有机会调用之前返回puts函数。

我的代码中的第二个 pthread_join 从未真正调用过,因为 main 确实从第一个 pthread_join 挂起,等待 c_thread 返回。在这个特定场景中的第二个连接是“无操作”,程序永远不会真正到达它,因为消费者永远不会真正返回。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-27
    • 1970-01-01
    • 2014-11-04
    • 2016-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多