日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

pthread 立即停止线程_线程取消(pthread_cancel)

發布時間:2025/3/20 编程问答 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 pthread 立即停止线程_线程取消(pthread_cancel) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

基本概念

pthread_cancel調用并不等待線程終止,它只提出請求。線程在取消請求(pthread_cancel)發出后會繼續運行,

直到到達某個取消點(CancellationPoint)。取消點是線程檢查是否被取消并按照請求進行動作的一個位置.

與線程取消相關的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)

是說pthread_testcancel在不包含取消點,但是又需要取消點的地方創建一個取消點,以便在一個沒有包含取消點的執行代碼線程中響應取消請求.

線程取消功能處于啟用狀態且取消狀態設置為延遲狀態時,pthread_testcancel()函數有效。

如果在取消功能處處于禁用狀態下調用pthread_testcancel(),則該函數不起作用。

請務必僅在線程取消線程操作安全的序列中插入pthread_testcancel()。除通過pthread_testcancel()調用以編程方式建立的取消點意外,pthread標準還指定了幾個取消點。測試退出點,就是測試cancel信號.

取消點:

線程取消的方法是向目標線程發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_CANCEL_DEFERRED),這是系統默認的取消類型,即在線程到達取消點之前,不會出現真正的取消;另外一種是異步取消(PHREAD_CANCEL_ASYNCHRONOUS),使用異步取消時,線程可以在任意時間取消。

線程終止的清理工作

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) \ {struct_pthread_cleanup_buffer _buffer; \

_pthread_cleanup_push (&_buffer, (routine), (arg));#define pthread_cleanup_pop(execute) \ _pthread_cleanup_pop (&_buffer, (execute)); \

}

可見,pthread_cleanup_push()帶有一個"{",而pthread_cleanup_pop()帶有一個"}",因此這兩個函數必須成對出現,且必須位于程序的同一級別的代碼段中才能通過編譯。

在下面的例子里,當線程在"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)

{

pthread_mutex_unlock(&mutex);

}void* thread0(void*arg)

{

pthread_cleanup_push(cleanup, NULL);//thread cleanup handler p

thread_mutex_lock(&mutex);

pthread_cond_wait(&cond, &mutex);

pthread_mutex_unlock(&mutex);

pthread_cleanup_pop(0);

pthread_exit(NULL);

}

總結

以上是生活随笔為你收集整理的pthread 立即停止线程_线程取消(pthread_cancel)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。