Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學

Linux 多執行緒程式設計完整指南:pthread 建立、同步、屬性與分離狀態

編輯:Linux 系統常見問題解答

一、執行緒建立基礎

標頭檔與編譯

#include 

// 編譯需連結 pthread 庫
gcc -o main main.c -lpthread
// 或
g++ -o main main.cpp -lpthread

pthread_create 原型

int pthread_create(pthread_t *thread,
                   const pthread_attr_t *attr,
                   void *(*start_routine)(void *),
                   void *arg);

參數詳解

參數說明
thread輸出參數,儲存新建立的執行緒 ID
attr執行緒屬性物件,NULL 表預設屬性
start_routine執行緒進入函數,單一 void* 參數,回傳 void*
arg傳遞給 start_routine 的參數

回傳值

  • 0:成功
  • 錯誤碼 (如 EAGAIN, EINVAL, EPERM):失敗,*thread 內容未定義

最小範例

#include 
#include 
#include 

void print_ids(const char *prefix) {
    pid_t pid = getpid();
    pthread_t tid = pthread_self();
    printf("%s pid %u tid %u (0x%x)\n", prefix, (unsigned)pid, (unsigned)tid, (unsigned)tid);
}

void* thread_func(void *arg) {
    print_ids("new thread:");
    return NULL;
}

int main() {
    pthread_t tid;
    int err = pthread_create(&tid, NULL, thread_func, NULL);
    if (err) {
        fprintf(stderr, "create failed: %s\n", strerror(err));
        return 1;
    }
    print_ids("main thread:");
    pthread_join(tid, NULL);  // 等待子執行緒結束
    return 0;
}

二、執行緒同步:pthread_join

int pthread_join(pthread_t thread, void **retval);
  • 阻塞呼叫執行緒,直到 thread 結束
  • retval 接收執行緒回傳值 (start_routine 的 return 值)
  • 回收執行緒資源 (joinable 狀態下必須 join 或 detach,否則洩漏)
  • 若執行緒已結束,立即返回

三、執行緒分離狀態:Joinable vs Detached

比較表

特性Joinable (預設)Detached
資源回收需 pthread_join 回收系統自動回收
取得回傳值可透過 join 取得不可取得
同步等待支援不支援
適用場景需同步、需回傳值的工作獨立背景任務、Fire-and-forget

設定分離狀態的兩種方式

// 方式 1:建立時透過屬性設定
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&tid, &attr, func, arg);
pthread_attr_destroy(&attr);

// 方式 2:執行緒內自我分離
void* func(void *arg) {
    pthread_detach(pthread_self());
    // ...
}

競態風險與避免

若分離執行緒極快結束,pthread_create 可能尚未回傳執行緒 ID,導致主執行緒取得無效 ID。解決:在子執行緒開頭加短暫延遲 (usleep/nanosleep) 或使用條件變數同步。

四、執行緒屬性進階設定

常用屬性

  • detachstate:分離狀態 (上述)
  • stacksize:堆疊大小 (最小 PTHREAD_STACK_MIN,通常 1MB 預設)
  • guardsize:保護頁大小 (防堆疊溢位)
  • schedpolicy / schedparam:排程策略與優先權 (需 root 權限)
  • inheritsched:繼承父執行緒排程屬性

屬性物件生命週期

pthread_attr_t attr;
pthread_attr_init(&attr);        // 初始化 (預設值)
// 設定各屬性...
pthread_create(&tid, &attr, func, arg);
pthread_attr_destroy(&attr);     // 銷毀,釋放內部資源

五、完整範例:帶參數傳遞、回傳值、錯誤處理

#include 
#include 
#include 
#include 
#include 

typedef struct {
    int id;
    char *msg;
} thread_arg_t;

void* worker(void *arg) {
    thread_arg_t *ta = (thread_arg_t*)arg;
    printf("Thread %d: %s\n", ta->id, ta->msg);
    sleep(1);
    char *ret = malloc(32);
    snprintf(ret, 32, "Result from thread %d", ta->id);
    return ret;  // 回傳動態分配記憶體
}

int main() {
    pthread_t t1, t2;
    thread_arg_t a1 = {1, "Hello"}, a2 = {2, "World"};
    void *res1, *res2;

    if (pthread_create(&t1, NULL, worker, &a1) != 0) return 1;
    if (pthread_create(&t2, NULL, worker, &a2) != 0) return 1;

    pthread_join(t1, &res1);
    pthread_join(t2, &res2);

    printf("Joined: %s\n", (char*)res1);
    printf("Joined: %s\n", (char*)res2);
    free(res1); free(res2);
    return 0;
}

常見錯誤與除錯提示

  • 忘記 -lpthread:連結錯誤 undefined reference to pthread_create
  • 傳遞區域變數指標:主執行緒結束前子執行緒仍在存取 → 傳遞動態記憶體或確保生命週期
  • 未 join 也未 detach:執行緒結束後變成「殭屍執行緒」,洩漏資源
  • 在執行緒中呼叫 exit():會結束整個進程,請用 pthread_exit() 或 return
Copyright © Windows教程網 All Rights Reserved