POSIX 執行緒在單一行程與單一位址空間中提供並行執行。共用位址空間並不代表共用的可變狀態就是安全的:必須透過互斥鎖、條件變數或 C 原子操作建立所有權與記憶體可見性。
建立、終止與取消 #
pthread_create 會啟動 void *(*start_routine)(void *),並傳入一個指標引數。它會直接回傳錯誤號碼,而不是透過 errno 回傳。執行緒可以從其啟動常式返回、呼叫 pthread_exit,或回應取消要求而終止;返回等同於使用該回傳值呼叫 pthread_exit。呼叫 exit 或從 main 返回會終止整個行程,而初始執行緒呼叫 pthread_exit 時,其他執行緒會繼續執行。
可連接的執行緒會保留其結束值與資源,直到另一個執行緒成功呼叫 pthread_join。分離的執行緒會在終止時釋放這些資源,因此無法被連接。因此,每個已建立的執行緒都需要明確指定由某個執行緒負責連接或分離。執行緒不得連接自身,應用程式邏輯也必須確保只有一個執行緒會連接指定的目標執行緒。
void *worker(void *arg) {
return arg;
}
pthread_t thread;
int error = pthread_create(&thread, NULL, worker, value);
if (error == 0) {
void *result;
error = pthread_join(thread, &result);
}取消預設為啟用且延遲處理。pthread_cancel 會要求取消,但不保證立即終止。被指定為取消點的呼叫(包括條件等待)可以處理這項要求。跨越取消點取得資源的程式碼應安裝 pthread_cleanup_push 處理常式,或以其他方式建立清理規則;對會操作不變量的程式碼而言,非同步取消並不適用。
屬性與資源上限 #
如果建立執行緒時需要非預設行為,請初始化 pthread_attr_t,並在 pthread_create 返回後銷毀屬性物件。pthread_attr_setdetachstate 用來選擇建立可連接或分離的執行緒。pthread_attr_setstacksize、pthread_attr_setstack 與 pthread_attr_setguardsize 控制堆疊配置與防護頁;應用程式提供的堆疊必須持續保持映射狀態,並且在執行緒終止前只能由該執行緒使用。
排程繼承、排程原則、優先權參數與競爭範圍也屬於執行緒屬性。是否支援要求的排程原則,以及設定該原則所需的權限,取決於實作。應將 pthread_attr_setaffinity_np 等 Linux 專用介面隔離在平台邊界之後。每個執行緒都會消耗堆疊位址空間與執行階段中繼資料,因此無限制地為每個要求建立執行緒會造成資源耗盡。
互斥鎖與條件變數 #
條件變數代表受互斥鎖保護的述詞發生變更,而不是代表述詞本身。應在持有互斥鎖時檢查述詞,在迴圈中等待,在持有同一個互斥鎖時使述詞變為真或假,然後發出訊號或廣播。
pthread_mutex_lock(&mutex);
while (!ready)
pthread_cond_wait(&condition, &mutex);
consume();
pthread_mutex_unlock(&mutex);pthread_cond_wait 會以原子方式釋放互斥鎖,並開始等待另一個取得互斥鎖且向條件發出訊號的執行緒。它會在返回前重新取得互斥鎖。這個原子交接可防止在檢查述詞與進入阻塞之間遺失述詞更新。迴圈仍然必要,因為喚醒可能是虛假的,而且在被喚醒的執行緒重新取得互斥鎖之前,另一個取用者可能會變更述詞。
pthread_cond_timedwait 接受絕對截止時間。預設時鐘是 CLOCK_REALTIME;如果必須避免牆上時鐘調整影響逾時,請在初始化前將條件屬性的時鐘設定為 CLOCK_MONOTONIC。逾時或取消並不會免除函式重新取得互斥鎖後釋放該鎖的義務。
互斥鎖解鎖與之後一次成功的加鎖會建立發佈受保護狀態所需的同步。條件訊號不能取代互斥鎖,而對非原子共用物件進行未同步讀取仍然是資料競爭。只有在明確設計記憶體順序協定時,才應使用原子操作。
行程共用物件 #
PTHREAD_PROCESS_SHARED 要求實作讓互斥鎖或條件變數可跨行程使用。物件及其相關狀態必須位於真正共用的映射中,例如使用 shm_open 加上 MAP_SHARED 建立的映射,而不能位於分別配置、僅具有相同虛擬位址的記憶體中。由於某些物件類型與環境可能不支援行程共用,因此請檢查屬性與初始化錯誤。在任何執行緒或行程都不可能繼續使用互斥鎖或條件變數之前,不得銷毀它們。
POSIX 條件變數規格與 pthreads(7) 規定了該 API 及其在 Linux 上的行為。
評論
在 GitHub 上閱讀或評論(發表評論需要登入)