pthread 线程退出时自动释放资源
線程退出時自動釋放資源
今天碰到一個問題:主線程pthread_create一個子線程A,子線程pthread_mutex_lock,然后調用其他的函數fun,最后從fun返回后再pthread_mutex_unlock.
但是如果在fun中調用了pthread_exit異常退出,那么豈不是沒釋放鎖就退出了,這肯定會引起死鎖.
解決辦法一:
在fun中調用pthread_exit之前都先調用pthread_mutex_lock釋放鎖,
但是這就需要吧mutex作為參數傳給fun,如果fun再調用了其他函數,就得一層一層的把mutex傳下去,
而且要找到fun及其調用的函數中的pthread_exit然后再修改是很麻煩的,如果fun是一個第三方程序,而且退出是調用了exit而不是pthread_exit,那就更麻煩了.
解決辦法二:
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)
代碼示例如下:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h>#define THREAD_NUMBER 2 pthread_mutex_t mutex;void aa() {pthread_exit(NULL); }void* hello1(void *arg) { char *hello_str = (char *)arg;int oldtype;pthread_detach (pthread_self ()); pthread_cleanup_push(pthread_mutex_unlock, (void *) &mutex);pthread_mutex_lock(&mutex);sleep(2);printf("%s\n", hello_str);aa();pthread_mutex_unlock(&mutex);pthread_cleanup_pop(0); }void* hello2(void *arg) {char *hello_str = (char *)arg;pthread_detach (pthread_self ()); pthread_mutex_lock(&mutex);sleep(1);printf("%s\n", hello_str);pthread_mutex_unlock(&mutex); }int main(int argc, char *argv[]) {int i;int ret_val;pthread_t pt[THREAD_NUMBER];const char *arg[THREAD_NUMBER];arg[0] = "hello world from thread1";arg[1] = "hello world from thread2";pthread_mutex_init(&mutex,NULL);printf("Begin to create threads...\n");ret_val = pthread_create(&pt[0], NULL, hello1, (void *)arg[0]);if (ret_val != 0 ) {printf("pthread_create error!\n");exit(1);}ret_val = pthread_create(&pt[1], NULL, hello2, (void *)arg[1]);if (ret_val != 0 ) {printf("pthread_create error!\n");exit(1);}sleep(5);printf("Now, the main thread returns.\n");return 0; }$ gcc -o a.out test.c -lpthread
$ ./a.out
Begin to create threads…
hello world from thread1
hello world from thread2
Now, the main thread returns.
可以看出hello1()->aa()->pthread_exit(),當線程hello1退出后鎖已經釋放了
其實不光是釋放鎖,還可以釋放其他資源.
當然上述pthread_cleanup_push()/pthread_cleanup_pop()是有缺陷的,
比如線程處于PTHREAD_CANCEL_ASYNCHRONOUS狀態,上述代碼段就有可能出錯,
因為CANCEL事件有可能在 pthread_cleanup_push()和pthread_mutex_lock()之間發生,或者在 pthread_mutex_unlock()和pthread_cleanup_pop()之間發生,從而導致清理函數unlock一個并沒有加鎖的 mutex變量,造成錯誤。
因此,在使用清理函數的時候,都應該暫時設置成PTHREAD_CANCEL_DEFERRED模式。為此,POSIX的 Linux實現中還提供了一對不保證可移植的 pthread_cleanup_push_defer_np()/pthread_cleanup_pop_defer_np()擴展函數
總結
以上是生活随笔為你收集整理的pthread 线程退出时自动释放资源的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从狠活到好活,“东北二次元”诞生记
- 下一篇: 苹果基于英特尔的 Mac Mini 和