日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

pthread_clean_push和pthread_clean_up

 lifei_szdz 2013-01-08

pthread_clean_push和pthread_clean_up  

2012-06-16 16:26:41|  分類: C和C++語言 |  標(biāo)簽:pthread   |字號(hào) 訂閱

原文: http://hi.baidu.com/tju_ant/item/507566a7549bcadc5af19144
語法:
void pthread_cleanup_push(void (*routine)(void*), void *arg);
void pthread_cleanup_pop(int execute);//這里的int參數(shù),0是不執(zhí)行push的內(nèi)容,非0是執(zhí)行。
pthread_cleanup_push很簡單,功能跟atexit()差不多,只不過一個(gè)是線程一個(gè)是進(jìn)程。
用來push一些函數(shù)入棧,以便程退出時(shí)調(diào)用。 
pthread_cleanup_pop 則表示彈出通過pthread_cleanup_push入棧的函數(shù)中的棧頂函數(shù),它遵循先進(jìn)后出原則 。如果參數(shù)為0,則表示僅僅是彈出棧頂函數(shù)但不執(zhí)行該函數(shù),如果參數(shù)為非0,則表示彈出該函數(shù)并執(zhí)行該函數(shù)。
需要注意的問題有幾點(diǎn):
1,push與pop一定是成對(duì)出現(xiàn)的,少一個(gè)不行。
2,push可以有多個(gè),同樣的pop也要對(duì)應(yīng)的數(shù)量,遵循"先進(jìn)后出原則"。
push進(jìn)去的函數(shù)可能在以下三個(gè)時(shí)機(jī)執(zhí)行:
1,顯示的調(diào)用pthread_exit();
2,在cancel點(diǎn)線程被cancel。
3,pthread_cleanup_pop()的參數(shù)不為0時(shí)。
以上動(dòng)作都限定在push/pop涵蓋的代碼內(nèi)。
前面的2個(gè)比較好理解,關(guān)鍵是pthread_cleanup_pop參數(shù)問題,其實(shí)int那是因?yàn)閏沒有bool,這里的參數(shù)只有0與非0的區(qū)別,對(duì)pthread_cleanup_pop,參數(shù)是5和10都是一樣的,都是非0。
我們經(jīng)常會(huì)看到這樣的代碼:

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呢,他根本就不會(huì)執(zhí)行push進(jìn)來的函數(shù)指針指向的函數(shù)而是pop該函數(shù),沒錯(cuò),是不執(zhí)行,真要執(zhí)行了就麻煩了。
那為啥還得寫這句呢?
那是因?yàn)閜ush和pop是必須成對(duì)出現(xiàn)的,不寫就是語法錯(cuò)誤。
這么寫的目的主要是為了保證mutex一定可以被unlock,因?yàn)?,在pthread_mutex_lock和pthread_mutex_unlock之間可能發(fā)生任何事情,比如,存在N個(gè)cancel點(diǎn)導(dǎo)致線程被main或者其他線程給cancel,而cancel動(dòng)作是不會(huì)釋放互斥鎖的,這樣就鎖死啦。
  通過pthread_cleanup_push加入一個(gè)函數(shù)pthread_mutex_unlock,參照上面執(zhí)行時(shí)機(jī)的說明,在線程被cancel的時(shí)候,就可以作釋放鎖的清理動(dòng)作。如果線程正常執(zhí)行,知道運(yùn)行到pthread_cleanup_pop,那么鎖已經(jīng)被中間代碼里的pthread_mutex_unlock給釋放了,這時(shí)候如果pthread_cleanup_pop的參數(shù)不為0,則會(huì)在pop并執(zhí)行前面通過pthread_cleanup_push而push的函數(shù),這樣鎖就會(huì)再次釋放,當(dāng)然也就不對(duì)了,釋放了兩次。
所以,pthread_cleanup_pop(0)是必須的,因?yàn)椋紫纫蓪?duì)出現(xiàn),其次,我們不希望他真的執(zhí)行到這里釋放兩次。
同樣道理:

void *exit1(void *t)
{
printf("exit1\n");
}
void *child(void *t)
{
pthread_cleanup_push(exit1,NULL);
.....
pthread_exit(NULL);
pthread_cleanup_pop(0);
}

exit1函數(shù)是在pthread_exit(NULL)的時(shí)候執(zhí)行的,pthread_cleanup_pop的參數(shù)是不是0沒有關(guān)系,因?yàn)楦緢?zhí)行不到這里。
而換成這樣:

pthread_cleanup_push(exit1,NULL);
......
pthread_cleanup_pop(0);
pthread_exit(NULL);

則exit1不會(huì)執(zhí)行,因?yàn)閜op的參數(shù)是0,如果把pop的參數(shù)修改為1則會(huì)執(zhí)行exit1,那會(huì)執(zhí)行兩次嗎?NO,因?yàn)閳?zhí)行pthread_cleanup_pop(0)時(shí),已經(jīng)把通過pthread_cleanup_push(exit1,NULL)壓入棧的函數(shù)exit1彈出棧了,而且pthread_exit在push/pop block的外面,他不會(huì)觸發(fā)exit1.

pthread_cleanup_push(exit1,NULL);
pthread_cleanup_push(exit2,NULL);
........
pthread_cleanup_pop(0);
pthread_cleanup_pop(1);

那0和1分別控制的是誰?配對(duì)原則,從外到里一對(duì)一對(duì)的拔掉就可以了,顯然,0控制的是exit2.

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多