首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

POSIX線程創建與結束實戰:pthread_create、pthread_join、pthread_exit 完整示例

     編輯:關於C語言

POSIX線程創建與結束實戰:pthread_create、pthread_join、pthread_exit 完整示例

本文通過一個完整的「線程創建→運行→結束→回收」示例,詳細講解 pthread_create、pthread_exit、pthread_join 三大核心函數的參數、返回值、協作模式及常見錯誤。

一、核心API速覽

函數作用關鍵參數返回值
pthread_create創建線程thread(輸出ID), attr(屬性,通常NULL), start_routine(入口函數), arg(傳參)0成功,錯誤碼失敗
pthread_exit主動結束線程retval(退出狀態指針)不返回(線程終止)
pthread_join等待線程結束並回收資源thread(目標ID), retval(輸出退出狀態)0成功,錯誤碼失敗

二、完整示例代碼


#include 
#include 
#include 
#include 

// 全局變量:線程退出狀態、線程參數
int status = 0;
char param[] = "Thread function param";

// 線程入口函數
void *thread_func(void *arg) {
    printf("Thread running, param: %s\n", (char*)arg);
    printf("Old status: %d\n", status);
    
    status = 3;  // 修改全局狀態
    pthread_exit(&status); // 退出,返回狀態地址
    // 注意:此處代碼不會執行
    return NULL;
}

int main() {
    pthread_t tid;       // 線程ID
    int ret;
    void *thread_ret;    // 接收線程退出狀態
    
    printf("Creating thread...\n");
    
    // 1. 創建線程
    ret = pthread_create(&tid, NULL, thread_func, (void*)param);
    if (ret != 0) {
        fprintf(stderr, "pthread_create failed: %d\n", ret);
        return 1;
    }
    printf("Thread created, ID: %lu\n", (unsigned long)tid);
    
    // 2. 主線程繼續做其他事...
    sleep(1);
    
    // 3. 等待線程結束,回收資源,獲取退出狀態
    ret = pthread_join(tid, &thread_ret);
    if (ret != 0) {
        fprintf(stderr, "pthread_join failed: %d\n", ret);
        return 1;
    }
    
    printf("Thread joined, returned status: %d\n", *(int*)thread_ret);
    printf("Global status after join: %d\n", status);
    
    return 0;
}

三、運行結果解析

Creating thread...
Thread running, param: Thread function param
Old status: 0
Thread joined, returned status: 3
Global status after join: 3
  • 主線程調用 pthread_create,新線程開始執行 thread_func。
  • 新線程修改全局 status,調用 pthread_exit(&status) 退出,將 &status 作為退出值。
  • 主線程調用 pthread_join 阻塞等待,線程結束後解除阻塞,通過 thread_ret 獲取退出值指針,解引用得 3。
  • 全局 status 也被修改為 3(共享內存可見性)。

四、關鍵細節與陷阱

1. 線程退出方式的區別

鐵律:主線程必須 pthread_join 所有工作線程,或調用 pthread_exit 讓進程等待其他線程(但主線程退出值丟失)。

2. 退出值指針的有效性


// 錯誤:返回棧上局部變量地址
void *bad_func(void *arg) {
    int local = 42;
    pthread_exit(&local); // 危險!棧幀銷毀後地址失效
}

// 正確:返回堆內存、全局/靜態變量、或主線程傳入的緩衝區
void *good_func(void *arg) {
    int *result = malloc(sizeof(int));
    *result = 42;
    pthread_exit(result); // 調用者需 free
}

3. 分離態線程

  • pthread_detach(tid) 或屬性設置 PTHREAD_CREATE_DETACHED。
  • 分離態線程結束時自動回收資源,不可 pthread_join。
  • 適用於「發射後不管」的後台任務。

4. 線程屬性 pthread_attr_t

  • 棧大小(pthread_attr_setstacksize,默認通常 8MB)。
  • 分離態/可連接態。
  • 調度策略/優先級(實時調度需特權)。
  • 繼承調度屬性。

5. 常見錯誤

  1. 忘記鏈接 -lpthread → 鏈接錯誤。
  2. 傳遞棧上緩衝區給線程,主線程提前銷毀 → 線程讀到垃圾數據。
  3. pthread_join 同一線程兩次 → 未定義行為。
  4. 線程函數簽名錯誤:必須是 void* (*)(void*)。
  5. 全局變量無同步保護 → 數據競態(示例中 status 為演示簡化,實戰需互斥量)。

五、編譯運行


gcc -Wall -Wextra -pthread -o thread_demo thread_demo.c
./thread_demo

掌握 create/exit/join 三部曲,是POSIX多線程編程的入門必修課。記住:創建傳參、退出傳值、加入回收,資源不洩漏,邏輯不競態。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
方式說明退出值獲取
pthread_exit(retval)主動退出,可指定退出值指針pthread_join 的 retval 參數
return retval從入口函數返回,等價於 pthread_exit同上
exit() / _exit()結束整個進程,所有線程強制終止不可獲取單個線程退出值
主線程 return相當於 exit(),結束進程其他線程未完成會被強制結束