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

POSIX線程創建與結束基礎:pthread_create、pthread_exit、pthread_join 參數詳解

     編輯:關於C語言

POSIX線程創建與結束基礎:pthread_create、pthread_exit、pthread_join 參數詳解

線程是進程內的輕量級執行流。本文詳細講解 POSIX 線程庫 (pthread.h) 三大核心函數的原型、參數含義、返回值、屬性對象、編譯鏈接及典型調用流程,為後續同步、通信篇打基礎。

一、線程基礎概念

  • 線程屬於進程,共享進程地址空間 (全局變量、堆、代碼、文件描述符)。
  • 私有:棧、寄存器上下文、線程ID、errno、信號屏蔽字、優先級。
  • 進程創建時自動有一個主線程 (main),可創建多個子線程。
  • 進程結束 (exit/return from main) 會終止所有線程。

二、核心 API 詳解

1. pthread_create — 創建線程


#include 

int pthread_create(pthread_t *thread,
                   const pthread_attr_t *attr,
                   void *(*start_routine)(void*),
                   void *arg);
參數說明
thread輸出參數,成功時寫入新線程標識符 (pthread_t)
attr線程屬性對象指針,NULL 表示默認屬性 (可連接態、默認棧大小、繼承調度)
start_routine線程入口函數指針,簽名固定:void* (*)(void*)
arg傳遞給入口函數的唯一參數 (通用指針)
  • 返回:0 成功;錯誤碼 失敗 (如 EAGAIN 資源不足, EINVAL 屬性無效)。**不設置 errno**。
  • 新線程從 start_routine(arg) 開始運行。

2. pthread_exit — 主動退出線程


void pthread_exit(void *retval);
  • 參數 retval:退出狀態指針,可被 pthread_join 獲取。
  • 線程終止,釋放線程私有資源 (棧、TLS),**不釋放共享資源** (全局變量、堆內存、文件描述符)。
  • 若主線程調用,僅主線程退出,**進程不結束** (其他線程繼續運行),不同於 exit()。
  • 入口函數 return retval 等價於 pthread_exit(retval)。

3. pthread_join — 等待線程結束並回收


int pthread_join(pthread_t thread, void **retval);
  • 阻塞調用者,直到目標線程終止。
  • 回收線程資源 (棧、TLS、內核線程結構體) — **必須 join 或 detach,否則產生「殭屍線程」洩漏資源**。
  • 返回:0 成功;錯誤碼失敗 (如 ESRCH 線程不存在, EINVAL 非可連接態/自己 join 自己)。
  • 類比進程的 waitpid。

三、線程屬性對象 pthread_attr_t


pthread_attr_t attr;
pthread_attr_init(&attr);
// 設置屬性...
pthread_create(&tid, &attr, func, arg);
pthread_attr_destroy(&attr);
參數說明
thread目標線程 ID (由 pthread_create 獲取)
retval輸出參數,接收線程退出值指針 (即 pthread_exit 的參數)

四、編譯與鏈接


# 必須鏈接 pthread 庫
gcc -pthread -o prog thread_prog.c
# 或顯式
gcc -o prog thread_prog.c -lpthread
  • -pthread 同時處理編譯預定義宏和鏈接,**推薦使用**。
  • 頭文件路徑:/usr/include/pthread.h (glibc)。

五、典型調用流程


// 全局數據 (需同步保護)
int shared_data = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *worker(void *arg) {
    int id = *(int*)arg;
    for (int i=0; i<1000; i++) {
        pthread_mutex_lock(&mutex);
        shared_data++;
        pthread_mutex_unlock(&mutex);
    }
    pthread_exit(NULL); // 或 return NULL;
}

int main() {
    pthread_t t1, t2;
    int id1 = 1, id2 = 2;
    
    pthread_create(&t1, NULL, worker, &id1);
    pthread_create(&t2, NULL, worker, &id2);
    
    // 主線程做其他事...
    
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    
    printf("Final: %d\n", shared_data); // 2000
    return 0;
}

六、常見錯誤

  1. 忘記 -pthread → 鏈接錯誤 undefined reference to pthread_create。
  2. 入口函數簽名錯誤:必須 void* (*)(void*),不能有其他參數/返回類型。
  3. 傳遞棧上局部變量地址給線程,主線程提前銷毀 → 線程讀到垃圾值。
  4. 未 join 也未 detach → 線程結束後資源洩漏 (僵屍線程)。
  5. 主線程 return 0 導致進程退出,子線程被強制殺死未完成工作。
  6. pthread_join 同一線程兩次 / join 已分離線程 → EINVAL。
  7. 線程間共享數據無同步 (互斥量/原子操作) → 數據競態,未定義行為。

七、分離態線程

  • pthread_detach(tid) 或屬性設置 PTHREAD_CREATE_DETACHED。
  • 線程結束時**自動回收資源**,無需/不可 join。
  • 適用於「發射後不管」的後台任務 (日誌、監控、定時清理)。
  • 無法獲取退出值。

掌握 create/exit/join 鐵三角與屬性對象,是 POSIX 多線程編程的入門鑰匙。記住:創建傳參、退出傳值、加入回收、分離自回收、共享必同步。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
屬性設置函數說明
分離態pthread_attr_setdetachstatePTHREAD_CREATE_DETACHED (不可join, 自動回收) / PTHREAD_CREATE_JOINABLE (默認, 需join)
棧大小pthread_attr_setstacksize最小 PTHREAD_STACK_MIN (通常 16KB/64KB),默認 8MB (Linux)
棧地址pthread_attr_setstack指定棧內存區域 (高級用法)
調度策略/優先級pthread_attr_setschedpolicy/priority實時調度 SCHED_FIFO/RR 需特權
繼承調度pthread_attr_setinheritsched繼承創建者屬性 vs 顯式設置