執行緒清理函式

2021-08-03 05:32:55 字數 3344 閱讀 9356

下面是一篇關於該知識點的文字,覺得不錯,分享下:

下面的測試程式我們都省略錯誤檢查

如同程序可以呼叫atexit函式安排在他退出時需要呼叫的函式一樣,程序也可以安排在他退出時呼叫的

函式。這些清理函式記錄在棧中,所以他們執行的順序和註冊的順序是相反的。

#incldue

void pthread_cleanup_push(void (*rtn)(void *),void *arg);

void pthread_cleanup_pop(int execute);

引數rtn為指向呼叫的清理函式的指標,arg為傳給該清理函式的引數。

當執行緒執行緒執行下條件時呼叫清理函式。

1 呼叫pthread_exit時

2響應取消請求時。

3用非零execute引數呼叫pthread_cleanup_pop時。

(我們後面還將測試如果執行緒只是簡單的 return 返回,那麼會不會呼叫執行緒清理函式)

如果execute的引數為0,那麼並不呼叫清理函式。但是無論哪種情況,pthread_cleanup_pop都將

刪除最近一次pthread_cleanup_push呼叫而建立的清理函式。

在具體驗證上面三個條件前,還需要注意一點:

這兩個函式可以實現為巨集。所以必須在於執行緒相同的作用域中以匹配的形式呼叫

pthread_cleanup_push的巨集定義中可包含字元''就要在

pthread_cleanup_pop的定義中存在。

我們先來驗證第三個條件,(用非零execute引數呼叫pthread_cleanup_pop會呼叫清理函式)

在這個條件中我們會碰到上面提到的細節。

pop然後return 還是直接 return 。這樣的目的是想看看直接return是不是真的不會呼叫清理函式,

還排除 呼叫pop後有呼叫return 導致的呼叫清理函式無法分清是誰觸發清理函式的呼叫的。

在主函式中我們 建立了兩個執行緒 分別傳遞不同的引數 來驗證上面所說的。(傳遞0呼叫pop後再return,傳遞非0則直接return返回)

4 void clean(void *arg)

7 8 void *thread(void *arg)else

20 }

21 22 int main(void)

但是當我編譯這個程式的時候總會出現如下的錯誤:

test_pthread_clean_return_and_execute.c: in function 『thread』:

test_pthread_clean_return_and_execute.c:17:3: error: expected 『while』 before 『else』

然後就蒙了,不知道什麼意思。磨了半天,無奈又回去看書。

然後才發現,我一開始只注意到 push和pop要匹配出現。然後沒有注意到他們必須要在相同的

作用域中。應為push和pop的巨集定義中包含了''所以上面的程式。我將pop放在if判斷裡面

導致,巨集擴充套件後 ''匹配錯亂。所以導致了編譯錯誤。

所以我們將  執行緒啟動函式 void *thread(voif *arg)改為下面這個函式

8 void *thread(void *arg)

16 17         pthread_cleanup_pop(1);

18         pthread_cleanup_pop(1);

19         return ((void *)0);

20 }

現在我們就可以編譯成功了.

我們來看下輸出

thread start

first thread exit code:1

thread start

second handler

first handler

second thread exit code:0

從輸出中。我們看到 當呼叫return 直接返回時的確並未呼叫執行緒清理函式。

當呼叫當以 非零引數 呼叫pop 時執行緒的確呼叫了 執行緒清理函式。並且呼叫的順序是和註冊時的順序是相反的

我們可以把 上面正確的執行緒函式中的pop呼叫的引數 改為0,那麼執行緒退出時就應該不會呼叫註冊函式

17         pthread_cleanup_pop(0);

18         pthread_cleanup_pop(0);

修改後的程式輸出如下:

thread start

first thread exit code:1

thread start

second thread exit code:0

正如我預料的,執行緒退出時沒有呼叫 清理函式。

後面的驗證就簡單多了·。我們來驗證第乙個條件:

當執行緒呼叫pthread_exit退出時,會呼叫清理函式。

4 void clean(void *arg)

7 void *thread(void *arg)

15         pthread_cleanup_pop(0);

16         pthread_cleanup_pop(0);

17         return ((void *)0);

18 }

19 20 

21 int main(void)

我們建立執行緒時傳遞的是非零 引數,這樣新執行緒就會以呼叫pthread_exit函式結束。

至於後面的pop呼叫。完全是因為push和pop函式必須匹配出現。

程式輸出:

thread start:

second handler

first handler

thread exit code:1

執行緒正確的呼叫了清理函式

再來驗證第二個條件(響應取消請求時會呼叫清理函式)

在預設情況下 當呼叫

int pthread_cancel(pthread_t tid);

函式會使得 tid標識的執行緒的行為如同呼叫了引數為 pthread_canceled的pthread_exit函式。

4 void clean(void *arg)

7 8 void *thread(void *arg)

20 int main(void)

32         exit(0);

33 }

輸出如下:

thread start:

second handler

first handler

thread exit code:pthread_canceled

當新執行緒接收到取消訊號時,因為已經設定了非同步取消,所以執行緒會立刻退出。

輸出驗證了 當執行緒響應取消時會呼叫清理函式,並且返回值為pthread_canceled。

POSIX 執行緒清理函式

posix 多執行緒的 cleanup 函式 控制清理函式的函式有兩個,乙個是 pthread cleanup push 用來把清理函式壓入棧中,另乙個是 pthread cleanup pop 用來把棧中的函式彈出來。下面是這兩個函式的函式原型 include void pthread clean...

linux執行緒系列(5)執行緒清理和控制函式

執行緒清理函式有兩個push和pop函式 include void pthread cleanup push void rtn void void arg void pthread cleanup pop int execute 返回 成功返回0,否則返回錯誤編號 引數rtn 清理函式指標 arg ...

c 多執行緒 中止前清理

gcc lpthread std c99 o main main.c deepfuture deepfuture laptop mytest main 1chen1 2chen2 3chen6 4chen24 5chen120 6chen720 7chen5040 8chen40320 9chen3...