pthread_exit 函数的属性:哪个是正确的?

Properties of pthread_exit function : which one is right?

在 CSAPP 书第 12.3 节中,他们说..

The thread terminates explicitly by calling the pthread_exit function. If the main thread calls pthread_exit, it waits for all other peer threads to terminate and then terminates main thread and the entire process with a return value of thread_return.

但是在 pthread_exit 的手册页中:https://man7.org/linux/man-pages/man3/pthread_exit.3.html

Performing a return from the start function of any thread other than the main thread results in an implicit call to pthread_exit(), using the function's return value as the thread's exit status.

To allow other threads to continue execution, the main thread should terminate by calling pthread_exit() rather than exit(3).

两个关于pthread_exit的描述是不同的。第一个说主线程将等待 peer 而不是第二个。

所以我写了一个代码保证正确属性.

(我从When the main thread exits, do other threads also exit?那里借用了一些代码行)

(感谢https://whosebug.com/users/959183/laifjei

由于在pthread_exit之前调用了pthread_cancel,主线程取消t1线程成功,结果为喜欢,

但是,当我将代码修改为“42 行 -> 添加 //”和“44 行 -> 删除 //”时,主线程无法取消 t1,因为它已经终止。因此下面的结果看起来像,,

最后,我得出结论,手册页的 属性 是正确的。我说得对吗?

为什么 CSAPP 书中说“它等待所有其他对等线程终止”?

Two descriptions about pthread_exit are different. First one said main thread will wait for peer but not on second.

差别不大,而且不是您可以通过大多数方法轻松区分的方式。

特别是,无论主线程是立即终止还是等待其他线程终止才这样做,pthread_exit()函数就像exit()函数一样它没有 return。观察到在 pthread_exit() 调用和 main 调用结束之间插入到测试程序中的语句没有被执行确实会产生任何信息来帮助您确定线程终止的相对顺序。

因此,这个问题在很大程度上也没有实际意义。虽然确实有一些方法可以观察到差异,但差异很少。

不过,这里有一个更好的例子:

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

pthread_t main_thread;

void *wait_for_main(void *unused) {
    void *main_rval;

    // Wait for the main thread to terminate
    if ((errno = pthread_join(main_thread, &main_rval)) != 0) {
        perror("pthread_join");
    } else {
        fputs("The main thread was successfully joined\n", stderr);
    }
    fflush(stderr);
    return NULL;
}

int main(void) {
    pthread_t child_thread;

    main_thread = pthread_self();
    if ((errno = pthread_create(&child_thread, NULL, wait_for_main, NULL)) != 0) {
        perror("pthread_create");
    } else {
        fputs("The child thread was successfully started\n", stderr);
    }

    pthread_exit(NULL);
}

该程序 运行s 成功,正在打印...

The child thread was successfully started
The main thread was successfully joined

这表明主线程确实终止了(因为它已成功加入),并且另一个线程随后继续 运行(因为它向 stderr 写入了消息)。

你接着问...

Why does CSAPP book said that "it waits for all other peer threads to terminate"?

...但除了 Bryant、O'Hallaron 或他们的一位编辑之外,没有人可以明确地回答这个问题(也许不是所有——或任何一个——)。这里有一些可能性:

  • 这本书就是错的。它发生了。
  • 这本书不清楚或不精确,因为它指的是等待整个程序、操作系统或“主线程以外的其他东西”的其他变体。

或者我实际的最佳猜测:

  • 这本书是从操作系统的角度描述行为,而 Pthreads 文档是从 C 语言的角度描述它。很可能作为进程主线程的 OS 线程确实是等待其他线程终止的线程,但它在 运行ning 程序中的 C 语言语义以 pthread_exit().那就是这本书在谈论 pthread 实现细节,没有记录,可观察的 pthread 语义。