【问题标题】:Why pthread_join does not block and wait for the thread to finish?为什么 pthread_join 不阻塞并等待线程完成?
【发布时间】:2021-05-05 08:46:36
【问题描述】:
#include <stdio.h>
#include <pthread.h>

void* thread(void *v) {
    printf("The thread starts now\n");
    //pthread_exit(NULL);
}

int main() {
    int tid1;
    int retValue = 0;
    pthread_create(&tid1, NULL,thread, NULL);

    retValue = pthread_join(tid1, NULL);
    printf("Thread ID: %d, return value: %d\n",tid1, retValue);

    retValue = pthread_join(tid1, NULL);
    printf("Thread ID: %d, return value: %d\n",tid1, retValue);
    return 0;
}

有时输出是:

Thread ID: 1877241856, return value: 3
Thread ID: 1877241856, return value: 3
The thread starts now

Process finished with exit code 0

问题是:

  1. 根据定义,pthread_join 应该阻塞,等待thread 完成执行,然后执行它后面的代码。但是为什么在我的代码中,thread 在两个 pthread_join 完成之后运行?

  2. 根据定义,pthread_join返回0表示加入成功,但是为什么我的代码的retValue总是3,不管threadpthread_join函数之前还是之后运行?

【问题讨论】:

  • pthread_join 的返回值告诉你什么?
  • 来自编译器的编译器诊断消息在哪里?由于它不正确,因此在没有诊断的情况下无法编译。
  • 编译器说“格式指定类型'unsigned long',但参数的类型是'int'”。这很有帮助,但我不知道我应该阅读诊断消息。谢谢@AnttiHaapala
  • @NameNull 所以,下次用-Werror 编译,它们会变成错误。也许-Wall 也是...但我的意思是没有pthread_t原始 程序,它会说与pthread_create 的指针类型不兼容。

标签: c multithreading operating-system pthreads


【解决方案1】:

这段代码有很多错误:

  1. pthread_create() 的第一个参数应该是pthread_t,而不是int。它们很可能大小不同,或者可以互换,因此tid1 可能不是有效的 pthread id。

  2. 线程不返回 0 或任何其他值。没有return 声明。

  3. “成功时,pthread_join() 返回 0;出错时,返回错误号。” 线程的返回值(如果有的话)将被放入pthread_join() 的未使用的第二个参数中。被视为返回值的实际上是pthread_join() 调用本身的结果。这是一个错误。也许它与上面的#1有关?

【讨论】:

  • 在将tid1 设置为pthread_t 类型后,程序现在具有预期的行为。
【解决方案2】:

除了那些被 TrentP 发现的最糟糕的错误是

加入之前已加入的线程会导致未定义的行为。

即在同一个线程上调用pthread_join两次

retValue = pthread_join(tid1, NULL);
retValue = pthread_join(tid1, NULL);

完全错误,如果将 tid1 更改为 pthread_t 就可以正常工作是错误的。未定义的行为意味着第二次调用pthread_join 时可能发生任何事情-pthread_join 可以返回错误,pthread_join 可以返回成功,它可以崩溃,它可以挂起,它可以修改内存的某些其他部分,它可能会导致一个新线程被启动...

【讨论】:

  • 第二个retValue 语句是一个实验。我只是想知道当我加入一个已经加入的线程时会发生什么。现在第二个retValue 是3,这是一个错误,符合预期。
  • @NameNull 好的,所以您没有阅读我写的内容。这不是预期的。因为行为是未定义,所以您可以什么都没有。你只是不能调用它两次。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-18
  • 1970-01-01
相关资源
最近更新 更多