執行緒取消 pthread cancel

2021-07-11 02:54:38 字數 4183 閱讀 8824

基本概念

pthread_cancel呼叫並不等待執行緒終止,它只提出請求。執行緒在取消請求(pthread_cancel)發出後會繼續執行,

直到到達某個取消點(cancellationpoint)。取消點是執行緒檢查是否被取消並按照請求進行動作的乙個位置.

與執行緒取消相關的pthread函式

int pthread_cancel(pthread_t thread)

傳送終止訊號給thread執行緒,如果成功則返回0,否則為非0值。傳送成功並不意味著thread會終止。在成功傳送 

cancel

指令後,使用 

pthread_join

函式,等待指定的執行緒已經完全退出以後,再繼續執行;否則,很容易產生 「

段錯誤」。

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)

取消點:

執行緒取消的方法是向目標執行緒發cancel訊號,但如何處理cancel訊號則由目標執行緒自己決定,或者忽略、或者立即終止、或者繼續執行至cancelation-point(取消點),由不同的cancelation狀態決定。

執行緒接收到cancel訊號的預設處理(即pthread_create()建立執行緒的預設狀態)是繼續執行至取消點,也就是說設定乙個canceled狀態,執行緒繼續執行,只有執行至cancelation-point的時候才會退出。

pthreads標準指定了幾個取消點,其中包括:

(1)通過pthread_testcancel呼叫以程式設計方式建立執行緒取消點。 

(2)執行緒等待pthread_cond_wait或pthread_cond_timewait()中的特定條件。 

(3)被sigwait(2)阻塞的函式 

(4)一些標準的庫呼叫。通常,這些呼叫包括執行緒可基於阻塞的函式。 

預設情況下,將啟用取消功能。有時,您可能希望應用程式禁用取消功能。如果禁用取消功能,則會導致延遲所有的取消請求,

直到再次啟用取消請求。  

根據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();

注意:程式設計方面的考慮,如果執行緒處於無限迴圈中,且迴圈體內沒有執行至取消點的必然路徑,則執行緒無法由外部其他執行緒的取消請求而終止。因此在這樣的迴圈體的必經路徑上應該加入pthread_testcancel()呼叫.

取消型別(cancellation type)

我們會發現,通常的說法:某某函式是 cancellation points,這種方法是容易令人混淆的。

因為函式的執行是乙個時間過程,而不是乙個時間點。其實真正的 cancellation points 只是在這些函式中 cancellation type 被修改為 phread_cancel_asynchronous 和修改回 pthread_cancel_deferred 中間的一段時間。

執行緒終止的清理工作

posix的執行緒終止有兩種情況:正常終止和非正常終止。

執行緒主動呼叫pthread_exit()或者從執行緒函式中return都將使執行緒正常退出,這是可預見的退出方式;

非正常終止是執行緒在其他執行緒的干預下,或者由於自身執行出錯(比如訪問非法位址)而退出,這種退出方式是不可預見的。

不論是可預見的執行緒終止還是異常終止,都會存在資源釋放的問題,在不考慮因執行出錯而退出的前提下,如何保證執行緒終止時能順利的釋放掉自己所占用的資源,特別是鎖資源,就是乙個必須考慮解決的問題。

最經常出現的情形是資源獨佔鎖的使用:執行緒為了訪問臨界資源而為其加上鎖,但在訪問過程中被外界取消,如果執行緒處於響應取消狀態,且採用非同步方式響應,或者在開啟獨佔鎖以前的執行路徑上存在取消點,則該臨界資源將永遠處於鎖定狀態得不到釋放。外界取消操作是不可預見的,因此的確需要乙個機制來簡化用於資源釋放的程式設計。

在posix執行緒api中提供了乙個pthread_cleanup_push()/ pthread_cleanup_pop()函式,

對用於自動釋放資源—從pthread_cleanup_push()的呼叫點到pthread_cleanup_pop()之間的程式段中的終止動作(包括呼叫pthread_exit()和取消點終止)都將執行pthread_cleanup_push()所指定的清理函式。

api定義如下:

void pthread_cleanup_push(void (*routine) (void *), void *arg)

void pthread_cleanup_pop(int execute)

pthread_cleanup_push()/pthread_cleanup_pop()採用先入後出的棧結構管理,void routine(void *arg)函式

在呼叫pthread_cleanup_push()時壓入清理函式棧,多次對pthread_cleanup_push() 的呼叫將在清理函式棧中形成乙個函式鏈;

從pthread_cleanup_push的呼叫點到pthread_cleanup_pop之間的程式段中的終止動作(包括呼叫pthread_exit()和異常終止,不包括return)

都將執行pthread_cleanup_push()所指定的清理函式。

在執行該函式鏈時按照壓棧的相反順序彈出。execute引數表示執行到 pthread_cleanup_pop()時

是否在彈出清理函式的同時執行該函式,為0表示不執行,非0為執行;這個引數並不影響異常終止時清理函式的執行。

pthread_cleanup_push()/pthread_cleanup_pop()是以巨集方式實現的,這是pthread.h中的巨集定義:

#define pthread_cleanup_push(routine,arg) \
可見,pthread_cleanup_push()帶有乙個"",因此這兩個函式必須成對出現,且必須位於程式的同一級別的**段中才能通過編譯。

在下面的例子裡,當執行緒在"do some work"中終止時,將主動呼叫pthread_mutex_unlock(mut),以完成解鎖動作。

pthread_cleanup_push(pthread_mutex_unlock, (void*) &mut);

pthread_mutex_lock(&mut);

/*do some work

*/pthread_mutex_unlock(&mut);

pthread_cleanup_pop(0);

或者void cleanup(void *arg)

void* thread0(void*arg)

執行緒操作 取消執行緒

include include include include 包含執行緒庫 void thread function void arg 定義執行緒函式原型 int main sleep 3 睡眠3秒 printf 取消執行緒.n res pthread cancel a thread 傳送取消執行...

執行緒取消點

執行緒取消 取消操作允許執行緒請求終止其所在程序總的任何其他執行緒。不需要執行緒執行進一步操作時,可以選擇取消操作。取消點 如果執行緒模式設定的是非同步模式的話,那只有到取消點才會取消執行緒。下面會講到兩種取消方式。那取消點有哪些呢?1 通過pthread testcancel 呼叫已程式設計方式建...

posix執行緒 執行緒的取消

初看這個主題時,覺得實在簡單。在我印象中,執行緒取消的實現通常是宣告乙個全域性變數來代表取消標誌,乙個執行緒在最開始的大while中判斷該標誌是否被設定,如果被設定就跳出迴圈。但是這有乙個問題是,如果程式中有n個執行緒都有可能被取消,那麼我們是否要宣告n個全域性變數來單獨控制它們的取消?posix提...