关于pthread_join函数阻塞主线程及多线程执行逻辑的技术咨询
pthread_join 运行逻辑详解
核心结论
pthread_join() 的核心作用就是阻塞调用它的线程(此处为你的主线程),直到指定的子线程完全终止,之后调用线程才会恢复执行后续代码。
针对你的疑问逐一解释
1. 手册描述的准确含义
Linux 手册中对 pthread_join() 的说明:
The pthread_join() function waits for the thread specified by thread to terminate
这句话的准确解读:
- 调用
pthread_join()的线程(比如主线程)会进入阻塞状态,暂停执行后续代码; - 子线程与主线程在调用
pthread_create()后是独立并行运行的,但主线程执行到pthread_join()时会停在这里,必须等指定子线程跑完才会继续; - 不是说主线程“只能在子线程结束后才能结束”——如果主线程不调用
pthread_join(),它可以先于子线程结束,此时子线程会变成“孤儿线程”由系统接管,但你的代码里因为调用了pthread_join(),所以主线程必须等子线程结束才能执行后续循环,最终结束进程。
2. 单线程测试的现象本质
你运行单线程代码时,子线程先跑完10000次循环,主线程才执行后续100次循环,这正是 pthread_join() 阻塞特性的体现:
- 主线程调用
pthread_create()后,子线程立刻开始执行function中的循环; - 主线程继续执行到
pthread_join(start, NULL),此时子线程还在运行,主线程被阻塞,暂停在此处; - 直到子线程完成所有循环、线程终止,
pthread_join()才会返回,主线程才会继续执行后面的for循环。
3. 多子线程时的协调逻辑
当你取消注释创建两个子线程后,Child1 和 Child2 输出交叉,且主线程要等两个子线程都结束才继续,原因如下:
- 两次调用
pthread_create()后,Child1和Child2会被操作系统调度,并行执行(CPU会在两个线程间快速切换,所以输出交叉); - 主线程先调用
pthread_join(start, NULL),此时会阻塞直到Child1终止; Child1终止后,主线程继续执行下一行pthread_join(start_2, NULL),再次阻塞直到Child2终止;- 只有当两个
pthread_join()都返回后,主线程才会进入最后的100次循环。
整理后的测试代码
#define _GNU_SOURCE #include<stdio.h> #include <stdint.h> #include <stdlib.h> #include <unistd.h> #include <assert.h> #include <sched.h> #include <sys/mman.h> #include <sys/types.h> #include <sys/wait.h> #include <pthread.h> #include "../utils/memory_utils.h" #include "../utils/cache_utils.h" #include "../utils/misc_utils.h" void function(char *str){ for(int i=0;i<10000;i++){ printf("%s thread: %d\n", str, i); } } int main(){ char *str = "string"; pthread_t start,start_2; if (pthread_create(&start, NULL, (void *)function, "Child1") != 0) { perror("pthread_create: trojan"); } if (pthread_create(&start_2, NULL, (void *)function, "Child2") != 0) { perror("pthread_create: trojan"); } pthread_join(start, NULL); pthread_join(start_2, NULL); for(int i=0;i<100;i++){ printf("Parent thread: %d\n", i); } return 0; }
额外补充
- 如果不想让主线程阻塞,可以不调用
pthread_join(),但要注意:主线程结束后整个进程会终止,所有子线程会被强制杀死,因此如果需要子线程完成任务,pthread_join()是最安全的等待方式; - 多个
pthread_join()的调用顺序不影响子线程的执行顺序——子线程的调度由操作系统决定,pthread_join()只是单纯等待指定线程结束,不会干预其他线程的运行。
内容的提问来源于stack exchange,提问作者Gerrie
相关产品推荐
相关产品推荐

