c++如何使用pthread_join函式配合pthread_create函式來建立和等待執行緒完成,實現執行緒同步與控制

海_纳百川發表於2024-10-15

在C++中,pthread_createpthread_join 是 POSIX 執行緒庫(pthread)的一部分,用於建立和管理執行緒。pthread_create 用於建立一個新的執行緒,而 pthread_join 用於等待一個執行緒的執行完成,從而實現執行緒同步與控制。

基本步驟

  1. 使用 pthread_create 函式建立一個執行緒。
  2. 執行緒的工作由一個執行緒函式來完成,該函式的簽名必須是 void* threadFunc(void* arg)
  3. 使用 pthread_join 函式等待執行緒執行完成,並獲取執行緒的退出狀態。

以下是如何在C++中使用 pthread_createpthread_join 來建立執行緒並等待其完成的示例:

示例程式碼

#include <iostream>
#include <pthread.h>  // POSIX 執行緒庫標頭檔案
#include <unistd.h>   // sleep 函式

// 執行緒執行的函式
void* threadFunc(void* arg) {
    int* id = static_cast<int*>(arg);  // 傳入的引數型別轉換
    std::cout << "Thread " << *id << " is running." << std::endl;
    sleep(2);  // 模擬執行緒工作
    std::cout << "Thread " << *id << " has finished." << std::endl;
    return nullptr;
}

int main() {
    const int numThreads = 3;
    pthread_t threads[numThreads];  // 儲存執行緒ID
    int threadArgs[numThreads];     // 執行緒的引數

    // 建立多個執行緒
    for (int i = 0; i < numThreads; ++i) {
        threadArgs[i] = i + 1;  // 為每個執行緒傳遞不同的引數
        if (pthread_create(&threads[i], nullptr, threadFunc, &threadArgs[i]) != 0) {
            std::cerr << "Error creating thread " << i + 1 << std::endl;
            return 1;
        }
    }

    // 等待所有執行緒完成
    for (int i = 0; i < numThreads; ++i) {
        if (pthread_join(threads[i], nullptr) != 0) {
            std::cerr << "Error joining thread " << i + 1 << std::endl;
            return 1;
        }
        std::cout << "Thread " << i + 1 << " has joined." << std::endl;
    }

    std::cout << "All threads have completed." << std::endl;
    return 0;
}

程式碼解析

  1. pthread_create:

    • 建立執行緒時使用 pthread_create,第一個引數是執行緒ID的指標,第二個引數是執行緒的屬性(可以傳入nullptr使用預設屬性),第三個引數是執行緒函式的地址,第四個引數是傳遞給執行緒函式的引數。
    • 每個執行緒會執行 threadFunc 函式,並接收不同的 threadArgs 作為引數。
  2. pthread_join:

    • 主執行緒使用 pthread_join 來等待子執行緒完成執行。pthread_join 的第一個引數是執行緒ID,第二個引數用於獲取執行緒的返回值(我們這裡傳入nullptr表示不關心返回值)。
    • pthread_join 可以保證主執行緒等待所有子執行緒執行完成後再繼續執行。
  3. threadFunc:

    • 這是子執行緒執行的函式。它的引數是 void* 型別,所以我們需要將其轉換為適當的型別(在此例中是 int*)。
    • 模擬執行緒任務時使用 sleep(2) 讓執行緒休眠2秒。
  4. 執行緒引數:

    • 為了避免多個執行緒共享同一個引數導致的問題,我們為每個執行緒分配一個單獨的引數 threadArgs[i]

輸出示例

Thread 1 is running.
Thread 2 is running.
Thread 3 is running.
Thread 1 has finished.
Thread 1 has joined.
Thread 2 has finished.
Thread 2 has joined.
Thread 3 has finished.
Thread 3 has joined.
All threads have completed.

執行緒同步與控制

透過使用 pthread_join,我們可以確保主執行緒在所有子執行緒執行完成之後才繼續執行,這樣可以避免主執行緒提前退出而導致子執行緒未完成的問題。這也是一種常見的執行緒同步機制。

注意事項

  1. 資料競爭: 如果多個執行緒同時訪問共享資源而不使用同步機制(如互斥鎖 pthread_mutex_t),可能會導致資料競爭。
  2. 執行緒返回值: 如果需要獲取執行緒的返回值,可以在 pthread_join 的第二個引數中提供指標接收執行緒函式的返回值。
  3. 執行緒的可重入性: 如果執行緒之間共享資料,應確保執行緒安全,避免資料競爭或不一致的狀態。

透過以上程式碼示例,你可以理解如何使用 pthread_createpthread_join 來實現多執行緒的同步與控制。

相關文章