API 速查
| 函數 | 原型 | 說明 |
pthread_exit | void pthread_exit(void* rval_ptr) | 線程退出,攜帶無類型指針返回值 |
pthread_join | int pthread_join(pthread_t tid, void** rval_ptr) | 阻塞等待線程 tid 結束,獲取返回值(可傳 NULL 忽略) |
完整示例:奇數線程睡眠,主線程按序回收
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
struct Args { char name[10]; int exit_code; };
void* thread_run(void* arg) {
Args* a = (Args*)arg;
printf("%s run, id:%u\n", a->name, (unsigned)pthread_self());
if (a->exit_code % 2) {
sleep(a->exit_code);
printf("im thread %d, here sleep %d second!\n", a->exit_code, a->exit_code);
}
pthread_exit((void*)&(a->exit_code)); // 返回指向 exit_code 的指針
}
int main() {
pthread_t tid[10];
Args a[10];
void* ec;
for (int i = 0; i < 10; ++i) {
sprintf(a[i].name, "thread_%d", i);
a[i].exit_code = i;
pthread_create(&tid[i], NULL, thread_run, &a[i]);
}
for (int i = 0; i < 10; ++i) {
pthread_join(tid[i], &ec); // 阻塞等待
printf("%s exit code is:%d\n", a[i].name, *(int*)ec);
}
return 0;
}
編譯與運行
g++ pthread_exit.cpp -lpthread -o pthread_exit
./pthread_exit
輸出分析
thread_0 run, id:968255760
thread_2 run, id:951470352
thread_1 run, id:959863056
...
thread_0 exit code is:0
im thread 1, here sleep 1 second!
thread_1 exit code is:1
thread_2 exit code is:2
im thread 3, here sleep 3 second!
thread_3 exit code is:3
...
- 所有線程併發啟動(運行順序不定)。
- 主線程
pthread_join(tid[0]) 先等待 thread_0(無睡眠,立即返回)。
- 隨後
join(tid[1]) 阻塞 1 秒,直到 thread_1 睡眠結束退出。
- 以此類推,主線程按創建順序串行回收,總耗時 ≈ 奇數秒之和 (1+3+5+7+9=25s)。
關鍵注意點
- 返回值生命周期:示例中傳
&a[i].exit_code,因 a[i] 在 main 結束前存活,安全。若傳局部變量地址會導致懸空指針。
pthread_join 只能調用一次/線程;重複調用行為未定義。
- 若不關心返回值,傳
NULL:pthread_join(tid, NULL)。
- 線程分離(
pthread_detach)後不可 join,資源自動回收。
最佳實踐
- 線程參數用
malloc 分配,線程內 free,避免棧變量生命周期問題。
- 返回值動態分配:
int* ret = new int(code); pthread_exit(ret);,join 後 delete。
- 錯誤處理:檢查
pthread_create/join 返回碼(0 成功,非 0 錯誤碼)。