日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

pthread_cleanup_push

發(fā)布時間:2025/7/14 57 豆豆
生活随笔 收集整理的這篇文章主要介紹了 pthread_cleanup_push 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

線程終止時的清理

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

最經(jīng)常出現(xiàn)的情形是資源獨占鎖的使用:線程為了訪問臨界資源而為其加上鎖,但在訪問過程中被外界取消,如果線程處于響應取消狀態(tài),且采用異步方式響應,或者在打開獨占鎖以前的運行路徑上存在取消點,則該臨界資源將永遠處于鎖定狀態(tài)得不到釋放。外界取消操作是不可預見的,因此的確需要一個機制來簡化用于資源釋放的編程。

在POSIX線程API中提供了一個pthread_cleanup_push()/pthread_cleanup_pop()函數(shù)對用于自動釋放資源--從pthread_cleanup_push()的調(diào)用點到pthread_cleanup_pop()之間的程序段中的終止動作(包括調(diào)用pthread_exit()和取消點終止)都將執(zhí)行pthread_cleanup_push()所指定的清理函數(shù)。API定義如下:

?

void pthread_cleanup_push(void (*routine) (void *), void *arg)void pthread_cleanup_pop(int execute)

?

pthread_cleanup_push()/pthread_cleanup_pop()采用先入后出的棧結(jié)構(gòu)管理,void routine(void *arg)函數(shù)在調(diào)用pthread_cleanup_push()時壓入清理函數(shù)棧,多次對pthread_cleanup_push()的調(diào)用將在清理函數(shù)棧中形成一個函數(shù)鏈,在執(zhí)行該函數(shù)鏈時按照壓棧的相反順序彈出。execute參數(shù)表示執(zhí)行到pthread_cleanup_pop()時是否在彈出清理函數(shù)的同時執(zhí)行該函數(shù),為0表示不執(zhí)行,非0為執(zhí)行;這個參數(shù)并不影響異常終止時清理函數(shù)的執(zhí)行。

pthread_cleanup_push()/pthread_cleanup_pop()是以宏方式實現(xiàn)的,這是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()帶有一個"}",因此這兩個函數(shù)必須成對出現(xiàn),且必須位于程序的同一級別的代碼段中才能通過編譯。在下面的例子里,當線程在"do some work"中終止時,將主動調(diào)用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);

?

必須要注意的是,如果線程處于PTHREAD_CANCEL_ASYNCHRONOUS狀態(tài),上述代碼段就有可能出錯,因為CANCEL事件有可能在pthread_cleanup_push()和pthread_mutex_lock()之間發(fā)生,或者在pthread_mutex_unlock()和pthread_cleanup_pop()之間發(fā)生,從而導致清理函數(shù)unlock一個并沒有加鎖的mutex變量,造成錯誤。因此,在使用清理函數(shù)的時候,都應該暫時設(shè)置成PTHREAD_CANCEL_DEFERRED模式。為此,POSIX的Linux實現(xiàn)中還提供了一對不保證可移植的pthread_cleanup_push_defer_np()/pthread_cleanup_pop_defer_np()擴展函數(shù),功能與以下代碼段相當:

?

{ int oldtype; pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype); pthread_cleanup_push(routine, arg); ... pthread_cleanup_pop(execute); pthread_setcanceltype(oldtype, NULL); }

?

?

線程終止的同步及其返回值

一般情況下,進程中各個線程的運行都是相互獨立的,線程的終止并不會通知,也不會影響其他線程,終止的線程所占用的資源也并不會隨著線程的終止而得到釋放。正如進程之間可以用wait()系統(tǒng)調(diào)用來同步終止并釋放資源一樣,線程之間也有類似機制,那就是pthread_join()函數(shù)。

?

void pthread_exit(void *retval) int pthread_join(pthread_t th, void **thread_return)int pthread_detach(pthread_t th)

?

pthread_join()的調(diào)用者將掛起并等待th線程終止,retval是pthread_exit()調(diào)用者線程(線程ID為th)的返回值,如果thread_return不為NULL,則*thread_return=retval。需要注意的是一個線程僅允許唯一的一個線程使用pthread_join()等待它的終止,并且被等待的線程應該處于可join狀態(tài),即非DETACHED狀態(tài)。

如果進程中的某個線程執(zhí)行了pthread_detach(th),則th線程將處于DETACHED狀態(tài),這使得th線程在結(jié)束運行時自行釋放所占用的內(nèi)存資源,同時也無法由pthread_join()同步,pthread_detach()執(zhí)行之后,對th請求pthread_join()將返回錯誤。

一個可join的線程所占用的內(nèi)存僅當有線程對其執(zhí)行了pthread_join()后才會釋放,因此為了避免內(nèi)存泄漏,所有線程的終止,要么已設(shè)為DETACHED,要么就需要使用pthread_join()來回收。

?

關(guān)于pthread_exit()和return

理論上說,pthread_exit()和線程宿體函數(shù)退出的功能是相同的,函數(shù)結(jié)束時會在內(nèi)部自動調(diào)用pthread_exit()來清理線程相關(guān)的資源。但實際上二者由于編譯器的處理有很大的不同。

在進程主函數(shù)(main())中調(diào)用pthread_exit(),只會使主函數(shù)所在的線程(可以說是進程的主線程)退出;而如果是return,編譯器將使其調(diào)用進程退出的代碼(如_exit()),從而導致進程及其所有線程結(jié)束運行。

其次,在線程宿主函數(shù)中主動調(diào)用return,如果return語句包含在pthread_cleanup_push()/pthread_cleanup_pop()對中,則不會引起清理函數(shù)的執(zhí)行,反而會導致segment fault。

http://blog.csdn.net/newnewman80/article/details/6276788

轉(zhuǎn)載于:https://www.cnblogs.com/newlist/archive/2012/02/11/2346285.html

總結(jié)

以上是生活随笔為你收集整理的pthread_cleanup_push的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。