我可以使用pthread_join()来检查已终止的线程吗?

时间:2015-03-30 01:44:09

标签: pthreads

我需要知道某个线程是否已经终止(如果不是,我必须等待它) 如果我在终止线程上调用pthread_join(),它总是在我的glibc版本中返回成功。 但是pthread_join()的文档说如果线程已经终止,它必须返回代码ESRCH的错误 如果我致电pthread_kill(thread_id, 0),则会返回错误代码ESRCH(正如预期的那样) 在glibc内部的源代码中,我看到pthread_join()内部有一个简单的有效thread_id检查,但不检查线程是否存在。 在pthread_kill()里面有真正的检查(在某些内核的列表中)。 有我的测试程序:

#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

void * thread_func(void *arg)
{
    printf("Hello! I`m thread_func!\nGood-bye!\n");
    return NULL;
}

int main(void)
{
    int res;
    pthread_t thread_id;

    printf("Hello from main()!\n");
    pthread_create(&thread_id, NULL, thread_func, NULL);
    printf("Waiting...\n");
    sleep(3);

    res = pthread_join(thread_id, NULL);
    printf("pthread_join() returned %d (%s)\n", res, strerror(res));

    res = pthread_kill(thread_id, 0);
    printf("pthread_kill() returned %d (%s)\n", res, strerror(res));

    return 0;
}

它是输出:

    Hello!
    Waiting...
    Hello! I`m thread_func!
    Good-bye!
    pthread_join() returned 0 (Success)
    pthread_kill() returned 3 (No such process)

我的问题:使用pthread_join()来检查已终止的线程是否安全,或者我必须始终使用pthread_kill()?

2 个答案:

答案 0 :(得分:3)

当一个线程退出时,它的代码会停止运行但它的&#34;尸体&#34;留在四周,以便父母收集返回代码。(1)

所以,即使你认为线程完全消失了,但事实并非如此。

pthread_join的调用将检查所述尸体的返回码,以便向父母通知事情的结果。 收集完毕后,线程可以真正地休息。(2)

为什么pthread_join()返回成功代码而pthread_kill不是 - 你不允许杀死一个&#39;已经死了,但你 允许加入一个死了但仍然温暖的人: - )

您可以通过尝试以下代码来获得更好的教育,这些代码尝试加入线程两次:

#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

void * thread_func(void *arg) {
    printf("Hello! I`m thread_func!\nGood-bye!\n");
    return NULL;
}

int main(void) {
    int res;
    pthread_t thread_id;

    printf("Hello from main()!\n");
    pthread_create(&thread_id, NULL, thread_func, NULL);
    printf("Waiting...\n");
    sleep(3);

    res = pthread_join(thread_id, NULL);
    printf("pthread_join() returned %d (%s)\n", res, strerror(errno));

    res = pthread_join(thread_id, NULL);
    printf("pthread_join() returned %d (%s)\n", res, strerror(errno));

    return 0;
}

在我的系统上,我看到了:

Hello from main()!
Waiting...
Hello! I`m thread_func!
Good-bye!
pthread_join() returned 0 (No error)
pthread_join() returned 3 (No error)

换句话说,虽然线程已经死亡,但第一个pthread_join()仍在工作。


(1)如果您愿意,您可以pthread_detach一个线程,以便在终止时立即释放其资源。这将是:

pthread_create(&thread_id, NULL, thread_func, NULL);
pthread_detach(thread_id);

但我非常肯定,即使线程仍然存在,连接也会失败。

要查看线程是否仍在运行无论是否已分离,您只需使用:

if (pthread_kill(thread_id, 0) != 0)
    // Thread is gone.

(2)对于这个答案的病态语气道歉,我今天感觉有点黑暗: - )

答案 1 :(得分:1)

pthread_join结束了线程对资源的使用。当线程到达终点并准备好进行清理时,它返回0。线程不会消失&#39;所有这一切都是默认的。

归零意味着:

1. the thread got cleaned up
2. the thread WAS still there waiting

所以不,不要使用pthread_kill,你有一个错误的主要假设:线程,除非设置为不可连接,否则在线程返回时不退出并清理堆栈和内存资源。换句话说,在您的示例中,return NULL不会终止该线程。 pthread_join做了。

所以,是的,使用pthread_join等待线程完成。