线程的取消

线程的取消

  1. 什么是线程的取消?

    1. 一个线程杀死另外一个线程,就叫线程的取消
  2. 线程如何取消其它线程?

    1. 发送cancel信号,目标线程收到cancel信号后的行为是可以进行设置的;一般有三种行为:1、忽略cancel信号,2、立刻终止线程,3、运行至取消点后终止线程(这是默认的行为)
  3. 什么是取消点?

    1. 取消点就是一些特殊的函数,但是man手册并没有给出准确的函数,一般认为会引起阻塞的函数都是取消点,对于一些不是阻塞性的函数也可能是取消点!(具体是不是,还是要实际测一下,不过man帮助还是提拱了一些一定是取消点的c库函数,可以通过man 7 pthreads查看)
    2. 不过一般情况下,不会去随便使用一些线程取取消另外一个线程的,可能会引起很多未知错误,所以很多公司都会命令禁止使用线程的取消!
  4. 那么如何取消呢?

    1. 使用的是pthread_cancel函数

    2. 函数原型:

      int pthread_cancel(pthread_t thread);
      

      参数:需要取消哪个线程,直接填该线程id

      返回值:线程的函数一般情况下都是成功返回0,失败返回错误码的

  5. 代码示例:

    #include <stdio.h>
    #include <unistd.h>
    #include <pthread.h>
    void *threadFunc(void *p)
    {
        //sleep是一个阻塞性函数,是一个取消点
        sleep(1);
    
        printf("child thread\n");
    
        pthread_exit(NULL);
    }
    
    int main(int argc, char **argv)
    {
        pthread_t thid;
        pthread_create(&thid, NULL, threadFunc, NULL);
    
        //给子线程发送cancel信号
        pthread_cancel(thid);
        
        printf("main thread\n");
    
        pthread_join(thid, NULL);
        return 0;
    }
    
    运行结果:
    main thread
    

    可以看到运行结果只有主线程打印了,子线程中的打印没有打印出来,说明子线程运行到sleep后就被取消了!

  6. 在man帮助中认为printf可能是一个取消点,但是进过测试printf是否为取消点与是否加’\n’有关,测试代码如下

    #include <stdio.h>
    #include <unistd.h>
    #include <pthread.h>
    void *threadFunc(void *p)
    {
        //第一个printf加了'\n'
        printf("child thread1\n");
    
        //没加'\n'
        printf("child thread2");
    
        printf("child thread3\n");
    
        pthread_exit(NULL);
    }
    
    int main(int argc, char **argv)
    {
        pthread_t thid;
        pthread_create(&thid, NULL, threadFunc, NULL);
    
        //给子线程发送cancel信号
        pthread_cancel(thid);
        
        printf("main thread\n");
    
        pthread_join(thid, NULL);
        return 0;
    }
    
    输出结果:
    main thread
    child thread1
        
    将上面的代码第7行注释掉,结果是:
    main thread
    child thread2child thread3
    可以看到第二个打印和第三个打印粘在一起的,就说明是子线程收到cancel信号后,运行至第12行才取消的
    

    结论:printf打印里带’\n’时是取消点,否则不是

  7. 前面我说了,目标线程收到cancel信号的行为是可以改变的,那么下面就讲一下该怎进行设置

  8. 设置的函数原型:

    //设置线程收到cancel信号的行为是否是可以取消的
    int pthread_setcancelstate(int state, int *oldstate);
    //参数1:有两个宏可以选择
    	//PTHREAD_CANCEL_ENABLE:该宏是默认行为,可以被cancel。
    	//另一宏是PTHREAD_CANCEL_DISABLE:线程是不可取消的,
    	//如果收到取消请求,则会将其阻塞,直到启用取消功能。
    //参数2:oldstate:原来的cancel状态以便恢复之前的状态信息,一般置为NULL
    //返回值:成功返回0,失败返回错误码
    
    //设置线程收到cancel信号的取消行为
    int pthread_setcanceltype(int type, int *oldtype);
    //参数1:同样有两个宏可以选择
    	//宏1:PTHREAD_CANCEL_DEFERRED:取消请求被延迟到线程下一次调用一个函数,
    	//该函数是一个取消点(默认行为)
    	//宏2:PTHREAD_CANCEL_ASYNCHRONOUS:线程可以在任何时候被取消
    	//(通常情况下,它会在收到取消请求后立即取消,但系统不保证)
    //参数2:oldstate:原来的cancel类型以便恢复之前的类型信息,一般置为NULL
    
  9. 代码示例:

    #include <stdio.h>
    #include <unistd.h>
    #include <pthread.h>
    void *threadFunc(void *p)
    {
        //设置子线程收到cancel信号的行为不是终止
        /* pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); */
        
        //设置子线程任意时刻收到cancel信号都可以被取消
        /* pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); */
    
        printf("child thread1\n");
    
        printf("child thread3\n");
    
        pthread_exit(NULL);
    }
    
    int main(int argc, char **argv)
    {
        pthread_t thid;
        pthread_create(&thid, NULL, threadFunc, NULL);
    
        //给子线程发送cancel信号
        pthread_cancel(thid);
        
        printf("main thread\n");
    
        pthread_join(thid, NULL);
        return 0;
    }
    

    如果代码中没有取消点,还想在某处想要收到cancel信号后终止,可以使用pthread_testcancel()函数在需要终止的地方调用,手动设置取消点!

本人能力有限,如有错误望各位大佬不吝指正,原创不易,转载请注明出处!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值