linux執行緒之pthread_join
pthread_join使乙個執行緒等待另乙個執行緒結束。
**中如果沒有pthread_join;主線程會很快結束從而使整個程序結束,從而使建立的執行緒沒有機會開始執行就結束了。加入pthread_join後,主線程會一直等待直到等待的執行緒結束自己才結束,使建立的執行緒有機會執行。
所有執行緒都有乙個執行緒號,也就是threadid,其型別為pthread_t。 通過呼叫pthread_self()函式可以獲得自身的執行緒號。
如果你的主線程,也就是main函式執行的那個執行緒,在你其他執行緒退出之前就已經退出,那麼帶來的bug則不可估量。通過pthread_join函式會讓主線程阻塞,直到所有執行緒都已經退出。
int pthread_join(pthread_t thread, void **value_ptr);
thread:等待退出執行緒的執行緒號。
value_ptr:退出執行緒的返回值。
可以通過pthread_join()函式來使主線程阻塞等待其他執行緒退出,這樣主線程可以清理其他執行緒的環境。但是還有一些執行緒,更喜歡自己來清理退出 的狀態,他們也不願意主線程呼叫pthread_join來等待他們。我們將這一類執行緒的屬性稱為detached(分離的)。如果我們在呼叫 pthread_create()函式的時候將屬性設定為null,則表明我們希望所建立的執行緒採用預設的屬性,也就是jionable(此時不是detached)。
如果需要將屬性 設定為detached。則應該如下設定:
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, pthread_create_detached);
pthread_create(&pthreadid, &attr, myprocess, &arg);
警告:
執行緒可以通過自身執行結束來結束,也可以通過呼叫pthread_exit()來結束執行緒的執行。另外,執行緒甲可以被執行緒乙被動結束。這個通過呼叫pthread_cancel()來達到目的。
int pthread_cancel(pthread_t thread);
函式呼叫成功返回0。
當然,執行緒也不是被動的被別人結束。它可以通過設定自身的屬性來決定如何結束
執行緒的被動結束分為兩種,一種是非同步終結,另外一種是同步終結。非同步終結就是當其他執行緒呼叫pthread_cancel的時候,執行緒就立刻被結束。而同 步終結則不會立刻終結,它會繼續執行,直到到達下乙個結束點(cancellation point)。當乙個執行緒被按照預設的建立方式建立,那麼它的屬性是同步終結。
執行緒終止的三種方式:
執行緒只是從啟動例程中返回,返回值是執行緒的退出碼;
執行緒呼叫了pthread_exit函式;
執行緒可以被同一程序中的其他執行緒取消。
1 執行緒取消的定義一般情況下,執行緒在其主體函式退出的時候會自動終止,但同時也可以因為接收到另乙個執行緒發來的終止(取消)請求而強制終止。
2 執行緒取消的語義執行緒取消的方法是向目標執行緒發cancel訊號,但如何處理cancel訊號則由目標執行緒自己決定,或者忽略(當禁止取消時)、或者立即終止(當在取消點 或非同步模式下)、或者繼續執行至cancelation-point(取消點,下面將描述),總之由不同的cancelation狀態決定。
執行緒接收到cancel訊號的預設處理(即pthread_create()建立執行緒的預設狀態)是繼續執行至取消點再處理(退出),或在非同步方式下直接 退出。乙個執行緒處理cancel請求的退出操作相當於pthread_exit(pthread_canceled)。當然執行緒可以通過設定為 pthread_cancel_disable來拒絕處理cancel請求,稍後會提及。
執行緒的取消與執行緒的工作方式(joinable或detached)無關。
3 取消點根據posix標準,pthread_join()、 pthread_testcancel()、pthread_cond_wait()、 pthread_cond_timedwait()、sem_wait()、sigwait()等函式以及read()、write()等會引起阻塞的系 統呼叫都是cancelation-point,而其他pthread函式都不會引起cancelation動作。但是pthread_cancel的手冊頁聲稱,由於linuxthread庫與c庫結合得不好,因而目前c庫函式都不是cancelation-point;但cancel訊號會使執行緒從阻塞的系統呼叫中退出,並置eintr錯誤碼,因此可以在需要作為cancelation-point的系統呼叫前後呼叫pthread_testcancel(),從而達到posix標準所要求的目標,即如下**段:
pthread_testcancel();
retcode = read(fd, buffer,length);
pthread_testcancel();
使用前 須判斷執行緒id的有效性!即判斷並保證:thrd != 0 否則有可能會出現「段錯誤」的異常!
但是pthread_cancel的手冊頁聲稱,由於linuxthread庫與c庫結合得不好,因而目前c庫函式(比如read())在linux中都不是cancelation-point;但cancel訊號會使執行緒從阻塞的系統呼叫中退出,並置eintr錯誤碼,因此可以在需要作為cancelation-point的系統呼叫前後呼叫 pthread_testcancel(),從而達到posix標準所要求的目標,即如下**段:
pthread_testcancel();
retcode = read(fd, buffer, length);
pthread_testcancel();
4 程式設計方面的考慮如果執行緒處於無限迴圈中,且迴圈體內沒有執行至取消點的必然路徑,則執行緒無法由外部其他執行緒的取消請求而終止。因此在這樣的迴圈體的必經路徑上應該加入pthread_testcancel()呼叫。
當pthread_cancel()返回時,執行緒未必已經取消,可能僅僅將請求傳送給目標執行緒,而目標執行緒目前沒有到達取消點,如果要知道執行緒在何時中止,就需要在取消它之後呼叫pthread_join()。有乙個例外是當執行緒被detach後,不能這樣處理:
a) 當join乙個已經detached的執行緒時,返回einval;
b) 如果join後該執行緒設定為detached,則detach將不起作用。
因此,如果知道乙個執行緒可能會以分離方式執行,就不需要在pthread_cancel()後呼叫pthread_join()。
5 與執行緒取消相關的pthread函式int pthread_cancel(pthread_t thread)
傳送終止訊號給thread執行緒,如果成功則返回0,否則為非0值。傳送成功並不意味著thread會終止。
int pthread_setcancelstate(int state, int *oldstate)
設 置本執行緒對cancel訊號的反應,state有兩種值:pthread_cancel_enable(預設)和 pthread_cancel_disable,分別表示收到訊號後設為cancled狀態和忽略cancel訊號繼續執行;old_state如果不為 null則存入原來的cancel狀態以便恢復。
int pthread_setcanceltype(int type, int *oldtype)
設 置本執行緒取消動作的執行時機,type有兩種取值:pthread_cancel_deffered 和 pthread_cancel_asychronous,僅當cancel狀態為enable時有效,分別表示收到訊號後繼續執行至下乙個取消點再退出和 立即執行取消動作(退出);oldtype如果不為null則存入運來的取消動作型別值。
void pthread_testcancel(void)
檢查本執行緒是否處於canceld狀態,如果是,則進行取消動作,否則直接返回。
6 檢測乙個執行緒是否還活著的pthread函式
Linux 多執行緒 pthread
1.linux執行緒的發展 早在linux2.2核心中。並不存在真正意義上的執行緒,當時linux中常用的執行緒pthread實際上是通過程序來模擬的,也就是同過fork來建立 輕 程序,並且這種輕程序的執行緒也有個數的限制 最多只能有4096和此類執行緒同時執行。2.4核心消除了個數上的限制,並且...
C C 多執行緒程式設計之四 終止pthread執行緒
多執行緒程式設計之終止pthread執行緒 pthread是posix threads的簡稱,是posix的執行緒標準。終止執行緒似乎是多執行緒程式設計的最後一步,但絕不是本系列教材的結束。執行緒建立到執行緒終止,希望先給讀者乙個關於多執行緒程式設計的整體認識。1.終止pthread執行緒 pthr...
多執行緒程式設計之pthread執行緒深入理解
不同的平台和作業系統上 程序和執行緒的實現機制不完全一致 但是一般來說執行緒棧都是獨立的 只要得到位址就可以相互訪問 pthread是 posix threads 的簡稱,是posix的執行緒標準。前幾篇部落格已經能給你初步的多執行緒概念,在進一步學習執行緒同步等多執行緒核心知識之前,需要對多執行緒...