09LinuxC執行緒學習之pthread_cancel函式及其案例
阿新 • • 發佈:2021-01-07
1 pthread_cancel函式
int pthread_cancel(pthread_t thread);
/*
功能:殺死(取消)執行緒,其作用,對應程序中kill()函式。
成功:0;失敗:錯誤號。
參1:要殺死執行緒的tid。
*/
2 pthread_cancel函式案例
2.1 案例1
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
void *tfn(void *arg){
while (1){
printf("thread pid=%d, tid=%lu\n", getpid(), pthread_self());
sleep(1);
)
return NULL;
}
int main(int argc, char *argv[]){
pthread_t tid;
tid[i] = -1;
int ret = pthread_create(&tid[i], NULL, tfn, NULL);
if(ret != 0){
fprintf(stderr, "pthread_create failed:%s\n" , strerror(ret));
exit(1);
}
printf("main pid=%d, tid=%lu\n", getpid(), pthread_self());
sleep(5);
pthread_cancel(tid);//終止執行緒,但需要一個執行的CPU分片
if(ret != 0){
fprintf(stderr, "pthread_create failed:%s\n", strerror(ret));
exit(1);
}
while(1);
return 0;
}
上面程式碼結果,當我們每一秒在子執行緒列印,5秒後主執行緒呼叫cancel函式成功殺死子執行緒。
2.2 案例2
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
void *tfn1(void *arg)
{
printf("thread 1 returning\n");
return (void *)111;
}
void *tfn2(void *arg)
{
printf("thread 2 exiting\n");
pthread_exit((void *)222);
}
void *tfn3(void *arg)
{
while (1) {
//printf("thread 3: I'm going to die in 3 seconds ...\n");
//sleep(1);
//pthread_testcancel(); //自己新增取消點*/
}
return (void *)666;
}
int main(void)
{
pthread_t tid;
void *tret = NULL;
pthread_create(&tid, NULL, tfn1, NULL);
pthread_join(tid, &tret);
printf("thread 1 exit code = %d\n\n", (int)tret);
pthread_create(&tid, NULL, tfn2, NULL);
pthread_join(tid, &tret);
printf("thread 2 exit code = %d\n\n", (int)tret);
pthread_create(&tid, NULL, tfn3, NULL);
sleep(3);
pthread_cancel(tid);
pthread_join(tid, &tret);
printf("thread 3 exit code = %d\n", (int)tret);
return 0;
}
結果分析,上面程式碼是第三個執行緒在主執行緒結束後將被殺死,但是圖中並未殺死打印出:thread 3 exit codexxx,而是子執行緒繼續卡死執行while(1)迴圈。這是為什麼呢?這是因為呼叫pthread_cancel殺死子執行緒必須有系統呼叫函式,例如新增sleep()或者其它,注意if,switch這些不是系統呼叫,所以也不會給契機pthread_cancel殺死子執行緒。最好的方法是呼叫pthread_testcancel,它內部作了系統呼叫的處理。
3 總結pthread_cancel
- 1)pthread_cancel可以殺死子執行緒,但必須需要一個契機,這個契機就是系統呼叫。一般方法是呼叫pthread_testcancel提供契機處理。並且join再回收該被殺死的子執行緒的返回值為pthread.h中的巨集#define PTHREAD_CANCELED ((void *) -1)。