概述
本篇记录通过pthread_setcancelstate
确保线程退出前代码块一定会被执行。另外通过pthread_cleanup_push
和pthread_cleanup_pop
设定线程退出的执行函数,当然上述一组函数需要通过pthread_cancel
来触发。
例程
话不多说,直接代码伺候。
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
void clean_func1(void * arg)
{
printf("### %s is called!\n", __func__);
}
void clean_func2(void * arg)
{
printf("### %s is called!\n", __func__);
}
void *thread_loop(void * arg)
{
//设置清理函数,调用顺序:后进先出
pthread_cleanup_push(clean_func1, NULL);
pthread_cleanup_push(clean_func2, NULL);
//设置线程退出状态,此时为不可取消状态
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
//下面一旦开始执行middle的打印,则会等待end也执行完才会被pthread_cancel取消。
while(1) {
printf("Pthread print start...\n");
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
sleep(1);
//设置取消状态,此时为不可取消,直至end打印结束。
printf("Pthread print middle...\n");
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
sleep(2);
printf("Pthread print end...\n");
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
sleep(1);
}
//与pthread_cleanup_push相对应,1表示需要触发pthread_cleanup_push注册的函数。
pthread_cleanup_pop(1);
pthread_cleanup_pop(1);
return NULL;
}
int main()
{
pthread_t pid;
int err;
err=pthread_create(&pid, NULL, thread_loop,NULL);
if(err!=0) {
perror("pthread_create");
exit(0);
}
//落在middle打印和end打印之间触发pthread_cancel。
sleep(2);
printf(">>> Start cancel thread(%ld)...\n", pid);
err = pthread_cancel(pid);
if(err!=0) {
perror("cancel error:");
exit(0);
}
err = pthread_join(pid,NULL);
if(err!=0) {
perror("pthread_join error:");
exit(0);
}
return 0;
}
运行结果
Pthread print start...
Pthread print middle...
>>> Start cancel thread(140158190855936)...
Pthread print end...
### clean_func2 is called!
### clean_func1 is called!