操作執行緒的函式

2021-09-02 15:17:49 字數 4457 閱讀 2387

執行緒有一套完整的與其有關的函式庫呼叫,在標頭檔案中必須有#include,並且在編譯時用選項-lpthread來鏈結執行緒庫。

執行緒建立函式

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

呼叫成功時返回0,失敗返回非0錯誤**。常見錯誤碼:

返回值描述

eaggin

系統資源不夠,或者建立的執行緒的個數超過系統對乙個程序中的執行緒總數的限制。

einval

第二個引數attr不合法

eperm

沒有合適的許可權來設定排程策略或引數

第乙個引數是指向pthread_t型別的指標。執行緒被建立時,這個指標指向的變數中將被寫入乙個識別符號,我們用該識別符號來引用新執行緒。第二個引數設定執行緒的屬性,可以制定新建執行緒棧的大小,排程策略等,通常為預設屬性null,最後兩個引數分別告訴執行緒將要自動執行的函式和傳遞給該函式的引數。void *(*start_routine)(void *) 說明必須要傳遞乙個函式位址,該函式以乙個指向void的指標為引數,返回值也是乙個指向void型別的指標。因此,也可以傳遞乙個任一型別的引數並返回乙個任一型別的指標。

執行緒退出

下面三種方法中,執行緒會終止,但是程序不會終止(如果該執行緒不是程序組中最後乙個執行緒)

建立執行緒時start_routine函式執行了return,並且制定了返回值。

執行緒呼叫了pthread_exit。

其他執行緒呼叫了pthread_cancel函式取消了該執行緒。

如果執行緒組中的任何乙個執行緒呼叫了exit函式,或者主線程在main函式中執行了return語句,那麼整個執行緒組內的所有執行緒都會終止。

但是,pthread_exit和執行緒啟動函式start_routine執行return是有區別的。

在start_routine中的任何層級的函式執行pthread_exit()都會引發執行緒退出,而return只是在start_routine函式內執行才能導致執行緒退出。

void pthread_exit(void *retval);

終止呼叫該函式的執行緒並返回乙個指向某個物件的指標。該指標存放執行緒的「臨終遺言」,執行緒組內的其他執行緒可以通過pthread_join函式接受這個位址,從而獲得該執行緒退出時的臨終遺言。若沒有任何資訊需要傳達,只需要直接傳遞null指標。但不可以返回乙個指向區域性變數的指標,該執行緒呼叫該函式後,這個區域性變數就不存在了,將引起嚴重的程式漏洞。

可以有以下四種方法傳遞返回值:

如果是int型的變數,則可以使用「pthread_exit((int *)ret);」不推薦這種方法,c標準無法保證將int型轉換成指標後,再從指標轉換為int型時,資料一直保持不變。

使用全域性變數。

使用malloc在堆上分配的空間裡。但使用之後必須釋放該空間,以免引起記憶體洩漏。

使用字串常量,如「pthread_exit(「hello,world」);」。

使用start_routine函式的return語句傳遞返回值時,兩者的資料型別要保持一致。

若執行緒組的其他執行緒仍在執行的情況下,主線程卻用pthread_exit函式退出,那麼主線程將進入殭屍狀態,而其他執行緒不受影響。

執行緒的連線

執行緒庫提供了pthrea_join函式,用來等待某執行緒的退出並接收它的返回值。成為連線(joining)。

#include

int pthread_join(pthread_t thread, void **retval);

第乙個引數是要等待返回的執行緒的執行緒id,第二個引數用來接收返回值。

呼叫失敗時,返回如下錯誤碼

返回值描述

esrch

傳入的執行緒id不存在

einval

執行緒不是乙個可連線的執行緒或者已有其他執行緒連線

edeadlk

死鎖,兩個執行緒互相連線或者連線自己

pthread_join函式之所以能夠判斷是否死鎖和連線是否被其他執行緒捷足先登,因為目標執行緒的控制結構體struct pthread中,存在如下成員變數,記錄了該執行緒的連線者。

struct pthread *joinid;

該指標存在三種可能

1、null表示執行緒可連線,但是尚沒有其他執行緒呼叫pthread_join來連線它。

2、指向執行緒自身的struct pthread:表示該執行緒屬於自我了斷型,執行過分離操作,或者建立執行緒時,設定的分離屬性為pthread_create_detached,一旦退出,就自動釋放所有資源。

3、指向該執行緒組內的其他struct pthread:表示joinid對應的執行緒會負責連線。

根據等待的執行緒是否退出,可以得到如下兩種情況:

等待的執行緒尚未退出,呼叫該函式的執行緒會陷入阻塞。

等待的執行緒已經退出,該函式會將執行緒的返回值存放到retval指標指向的位置。

執行緒的連線操作類似於等待子程序退出的等待條件,但還有不同之處:

連線退出的執行緒的原因:

如果不執行連線操作,執行緒的資源就不能釋放,也不能被復用,會造成資源洩露。

當執行緒組內的其他執行緒呼叫pthread_join連線退出執行緒時,內部會呼叫__free_tcb函式負責釋放退出的執行緒的資源。

縱然呼叫了pthread_join,也並沒有立即呼叫munmap來釋放掉退出執行緒的棧,它們是被後建的執行緒復用了,這是nptl執行緒庫的設計。釋放執行緒資源的時候,nptl認為程序可能再次建立執行緒,而頻繁地munmap和mmap會影響效能,所以ntpl將該棧快取起來,放到乙個鍊錶之中, 如果有新的建立執行緒的請求,nptl會首先在棧快取鍊錶中尋找空間合適的棧,有的話,直接將該棧分配給新建立的執行緒。

始終不將執行緒棧歸還給系統也不合適,所以快取的棧大小有上限,預設是40mb,如果快取起來的執行緒棧的空間總和大於40mb, nptl就會掃瞄鍊錶中的執行緒棧,呼叫munmap將一部分空間歸還給系統。

執行緒的分離

預設情況下,新建立的執行緒處於可連線( joinable)的狀態,可連線狀態的執行緒退出後,需要對其執行連線操作,否則執行緒資源無法釋放,從而造成資源洩漏。

如果其他執行緒並不關心執行緒的返回值,那麼連線操作就會變成一種負擔: 你不需要它,但是你不去執行連線操作又會造成資源洩漏。這時候你需要的東西只是:執行緒退出時,系統自動將執行緒相關的資源釋放掉,無須等待連線。

nptl提供了pthread detach 函式來將執行緒設定成已分離( detached)的狀態,如果執行緒處於已分離的狀態,那麼執行緒退出時,系統將負責**執行緒的資源,如下:

#include

int pthread detach (pthread t thread);

可以是執行緒組內其他執行緒對目標執行緒進行分離,也可以是執行緒自己執行pthread detach函式,將自身設定成已分離的狀態,如下:

pthread detach(pthread self())

執行緒的狀態之中,可連線狀態和已分離狀態是衝突的,乙個執行緒不能既是可連線的,又是已分離的。因此,如果執行緒處於已分離的狀態,其他執行緒嘗試連線線程時,會返回einval錯誤。

pthread_detach

esrch  傳入的執行緒id不存在,查無此執行緒

einval 執行緒不是乙個可連線(joinable)的執行緒,已經處於已分離狀態

需要強調的是,不要誤解已分離狀態的內涵。所謂已分離,並不是指執行緒失去控制,不歸執行緒組管理,而是指執行緒退出後,系統會自動釋放執行緒資源。若執行緒組內的任意執行緒執行了exit 函式,即使是已分離的執行緒,也仍然會受到影響,一併退出。

將執行緒設定成已分離狀態,並非只有pthread_detach一種方法。另一種方法是在建立執行緒時,將執行緒的屬性設定為已分離:

#include

int pthread_attr_setdetachstate (pthread attr_ t *attr, int detachstate) ;

int pthread_attr_getdetachstate (pthread attr. t *attr, int *detachstate) ;

其中detachstate的可能值如表7-9所示。

說  明

pthread_create_joinable  預設情況,表示建立出來的執行緒會處於可連線的狀態

pthread_create_detached  表示建立出來的執行緒,會處於已分離的狀態

有了這個,如果確實不關心執行緒的返回值,可以在建立執行緒之初,就指定其分離屬性為pthread_create_detached。

執行緒取消

linux提供了如下函式來控制線程的取消:

#include

int pthread_cancel(pthread_ t thread);

乙個執行緒可以通過呼叫該函式向另一-個執行緒傳送取消請求。這不是個阻塞型介面,發出請求後,函式就立刻返回了,而不會等待目標執行緒退出之後才返回。

如果成功,該函式返回0,否則將錯誤碼返回。程式設計時不建議使用,該介面實現的功能似是而非。

執行緒操作函式彙總

函式 作用 執行緒id pthread self 獲取執行緒id syscall 224 獲取核心中的執行緒id 執行緒的建立和終止 pthread create 建立執行緒 pthread exit 執行緒終止 互斥量 pthread join 執行緒匯合 pthread mutex init 互...

Linux 執行緒操作函式總結

1 執行緒建立函式int pthread create pthread t restrict tidp,const pthread attr t restrict attr,void start rtn void void restrict arg 返回值 若是成功建立執行緒返回0,否則返回錯誤的編...

Linux 執行緒操作函式總結

1 執行緒建立函式 int pthread create pthread t restrict tidp,const pthread attr t restrict attr,void start rtn void void restrict arg 返回值 若是成功建立執行緒返回0,否則返回錯誤的...