<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"></script> <script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"></script>
void pthread_cleanup_pop(int execute);//這裏的int參數,0是不執行push的內容,非0是執行。
原型很簡單,功能跟atexit()差不多,只不過一個是線程一個是進程。
用來設置在push/pop內線程退出時要做的事情。
需要注意的問題有幾點:
1,push與pop一定是成對出現的,其實push中包含"{"而pop中包含"}",少一個不行。
2,push可以有多個,同樣的pop也要對應的數量,遵循"先進後出原則"。
push進去的函數可能在以下三個時機執行:
1,顯示的調用pthread_exit();
或
2,在cancel點線程被cancel。
或
3,pthread_cleanup_pop()的參數不爲0時。
以上動作都限定在push/pop涵蓋的代碼內。
前面的2個比較好理解,關鍵是pthread_cleanup_pop參數問題,其實int那是因爲c沒有bool,這裏的參數只有0與非0的區別,對pthread_cleanup_pop,參數是5和10都是一樣的,都是非0。
我們經常會看到這樣的代碼:
void child(void *t)
{
pthread_cleanup_push(pthread_mutex_unlock,&mutex);
pthread_mutex_lock(&mutex);
..............
pthread_mutex_unlock(&mutex);
pthread_cleanup_pop(0);
}
爲啥pthread_cleanup_pop是0呢,他根本就不會執行push進來的函數指針指向的函數,沒錯,是不執行,真要執行了就麻煩了。
那爲啥還得寫這句呢?
那是因爲push和pop是必須成對出現的,不寫就是語法錯誤。
這麼寫的目的主要是爲了保證mutex一定可以被unlock,因爲,在pthread_mutex_lock和pthread_mutex_unlock之間可能發生任何事情,比如,存在N個cancel點導致線程被main或者其他線程給cancel,而cancel動作是不會釋放互斥鎖的,這樣就鎖死啦。
通過pthread_cleanup_push加入一個函數pthread_mutex_unlock,參照上面執行時機的說明,在線程被cancel的時候,就可以作釋放鎖的清理動作。如果線程正常執行,知道運行到pthread_cleanup_pop,那麼鎖已經被中間代碼裏的pthread_mutex_unlock給釋放了,這時候如果pthread_cleanup_pop的參數不爲0,則會再次釋放,錯就錯在這裏了,釋放了兩次。
所以,pthread_cleanup_pop(0)是必須的,因爲,首先要成對出現,其次,我們不希望他真的執行到這裏釋放兩次。
同樣道理:
void *exit1(void *t)
{
printf("exit1/n");
}
void *child(void *t)
{
pthread_cleanup_push(exit1,NULL);
.....
pthread_exit(NULL);
pthread_cleanup_pop(0);
}
exit1函數是在pthread_exit(NULL)的時候執行的,pthread_cleanup_pop的參數是不是0沒有關係,因爲根本執行不到這裏。
而換成這樣:
pthread_cleanup_push(exit1,NULL);
......
pthread_cleanup_pop(0);
pthread_exit(NULL);
則exit1不會執行,因爲pop的參數是0,如果把pop的參數修改爲1則會執行exit1,那會執行兩次嗎?NO,因爲pthread_exit在push/pop block的外面,他不會觸發exit1.
pthread_cleanup_push(exit1,NULL);
pthread_cleanup_push(exit2,NULL);
........
pthread_cleanup_pop(0);
pthread_cleanup_pop(1);
那0和1分別控制的是誰?配對原則,從外到裏一對一對的拔掉就可以了,顯然,0控制的是exit2.
<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"></script>
|