Linux多线程3-5_线程清理操作

孤街醉人 提交于 2019-12-27 00:04:32

一、概念

1、线程可以安排它退出时的清理操作,这与进程的可以用atexit函数安排进程退出时需要调用的函数类似。这样的函数称为线程清理处理程序。线程
可以建立多个清理处理程序,处理程序记录在栈中,所以这些处理程序执行的顺序与他们注册的顺序相反

pthread_cleanup_push(void (rtn)(void), void *args)//注册处理程序
pthread_cleanup_pop(int excute)//清除处理程序

2、当执行以下操作时调用清理函数,清理函数的参数由args传入
1)、调用pthread_exit
2)、响应取消请求
3)、用非零参数调用pthread_cleanup_pop

3、清理函数的必要性
也许你会认为线程不需什么清理操作,我可以在退出之前把所有该办的事情办了。但是,你不能确保你的线程永远正常的退出,加入它被取消呢。
清理操作的优越性就在于,如果线程被取消了,那么清理函数会自动调用,这一点你是办不到的

4、清理函数要注意
pthread_cleanup_push() 和 pthread_cleanup_pop()是用宏定义继承的,宏定义中包含{},因此他们两要成对出席那

四、实例

return返回的线程不会执行清理操作,以非0参数调用pthread_cleanup_pop或者用pthread_exit退出的线程会执行清理操作

/*      
 *DESCRIPTION:    线程清理处理程序
 *    pthread_cleanup_push(void (*rtn)(void*), void *args)//注册处理程序
 *    pthread_cleanup_pop(int excute)//清除处理程序
 *
 *    这两个函数要成对的出现,否则编译无法通过
 *
 *    当执行以下操作时调用清理函数,清理函数的参数由args传入
 *    1、调用pthread_exit
 *    2、响应取消请求(请你来验证)
 *    3、用非零参数调用pthread_cleanup_pop
 */    

#include "apue.h"

void *fisrt_clean(void *arg)
{
    printf("%s fisrt clean\n", arg);
    return(void *)0;
}
void *second_clean(void *arg)
{
    printf("%s second clean\n", arg);
    return(void *)0;
}

void *thread_fun1(void *arg)
{
    printf("new thread 1\n");
    pthread_cleanup_push(fisrt_clean, "thread1");
    pthread_cleanup_push(second_clean, "thread1");

    pthread_cleanup_pop(1);
    pthread_cleanup_pop(0);

    return(void *)1;
}
void *thread_fun2(void *arg)
{
    printf("new thread 2\n");
    pthread_cleanup_push(fisrt_clean, "thread2");
    pthread_cleanup_push(second_clean, "thread2");

    pthread_exit((void *)2);
    pthread_cleanup_pop(0);
    pthread_cleanup_pop(0);

}

int main()
{
    pthread_t tid1, tid2;
    int err;

    err =pthread_create(&tid1, NULL, thread_fun1, NULL);
    if(err != 0)
    {
        printf("create new thread 1failed\n");
        return;
    }
    err =pthread_create(&tid2, NULL, thread_fun2, NULL);
    if(err != 0)
    {
        printf("create new thread 2failed\n");
        return;
    }

    sleep(2);

    return 0 ;
}

练习:当一个线程被取消,清理操作会执行

/*
 *DESCRIPTION:    线程清理处理程序
 *    pthread_cleanup_push(void (*rtn)(void*), void *args)//注册处理程序
 *    pthread_cleanup_pop(int excute)//清除处理程序
 *
 *    这两个函数要成对的出现,否则编译无法通过
 *
 *    当执行以下操作时调用清理函数,清理函数的参数由args传入
 *    1、调用pthread_exit
 *    2、响应取消请求
 *    3、用非零参数调用pthread_cleanup_pop
 */    

#include "apue.h"

void *fisrt_clean(void *arg)
{
    printf("%s fisrt clean\n", arg);
    return(void *)0;
}
void *second_clean(void *arg)
{
    printf("%s second clean\n", arg);
    return(void *)0;
}

void *thread_fun1(void *arg)
{
    printf("new thread 1 start\n");
    //设置清理函数
    pthread_cleanup_push(fisrt_clean, "thread1");
    pthread_cleanup_push(second_clean, "thread1");

    //休眠2s,程序回到主线程,让主线程执行取消操作
    sleep(2);

    pthread_cleanup_pop(1);
    pthread_cleanup_pop(0);

    printf("new thread 1 over\n");
    return(void *)1;
}
void *thread_fun2(void *arg)
{
    printf("new thread 2 start\n");
    //设置清理函数
    pthread_cleanup_push(fisrt_clean, "thread2");
    pthread_cleanup_push(second_clean, "thread2");

    //休眠2s,程序回到主线程,让主线程执行取消操作
    sleep(2);

    printf("new thread 2 over\n");
    pthread_exit((void *)2);
    pthread_cleanup_pop(0);
    pthread_cleanup_pop(0);

}

int main()
{
    pthread_t tid1, tid2;
    int err;

    printf("main thread start\n");
    //创造新线程
    err =pthread_create(&tid1, NULL, thread_fun1, NULL);
    if(err != 0)
    {
        printf("create new thread 1failed\n");
        return;
    }
    err =pthread_create(&tid2, NULL, thread_fun2, NULL);
    if(err != 0)
    {
        printf("create new thread 2failed\n");
        return;
    }

    //休眠1s,让新线程设置清理函数
    sleep(1);

    //取消新线程
    printf("main thread about to cancel new thread\n");
    err = pthread_cancel(tid1);
    if(err)
        printf("cancel new thread 1 failed\n");
    err = pthread_cancel(tid2);
    if(err)
        printf("cancel new thread 2 failed\n");

    //等待新线程结束
    printf("wait for new thread over\n");
    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);

    printf("main thread over\n");

    return 0 ;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!