Linux多线程3-3_线程取消

简介: 一、线程取消     将正在运行的线程取消执行,一个线程可以取消另一个线程,线程也可以自己取消自己。当线程被取消之后,会调用清理函数    二、取消函数     int pthread_cancel(pthread_t tid)     取消tid指定的线程,成功返回0。
一、线程取消
    将正在运行的线程取消执行,一个线程可以取消另一个线程,线程也可以自己取消自己。当线程被取消之后,会调用清理函数    

二、取消函数
    int pthread_cancel(pthread_t tid)
    取消tid指定的线程,成功返回0。但是取消只是发送一个请求,并不意味着等待线程终止,而且发送成功也不意味着tid一定会终止

三、取消状态
    1、概念
    取消状态,就是线程对取消信号的处理方式,忽略或者响应。线程创建时默认响应取消信号
    2、函数
    int pthread_setcancelstate(int state, int *oldstate)  
    设置本线程对Cancel信号的反应,state有两种值:PTHREAD_CANCEL_ENABLE(缺省)和PTHREAD_CANCEL_DISABLE,分别表示收到信号后设为CANCLED状态和忽略CANCEL信号继续运行;old_state如果不为NULL则存入原来的Cancel状态以便恢复。

四、取消类型
    1、概念
    取消类型,是线程对取消信号的响应方式,立即取消或者延时取消。线程创建时默认延时取消
    2、函数
    int pthread_setcanceltype(int type, int *oldtype) 
    设置本线程取消动作的执行时机,type由两种取值:PTHREAD_CANCEL_DEFFERED和PTHREAD_CANCEL_ASYCHRONOUS,仅当Cancel状态为Enable时有效,分别表示收到信号后继续运行至下一个取消点再退出和立即执行取消动作(退出);oldtype如果不为NULL则存入运来的取消动作类型值。

五、取消点
    取消一个线程,它通常需要被取消线程的配合。线程在很多时候会查看自己是否有取消请求。如果有就主动退出, 这些查看是否有取消的地方称为取消点很多地方都是包含取消点,包括:
pthread_join()、 pthread_testcancel()、pthread_cond_wait()、 pthread_cond_timedwait()、sem_wait()、sigwait()、write、read,大多数会阻塞的系统调用。你可以通过man pthreads来查看当前系统中那些操作是取消点

六、手册
PTHREAD_CANCEL(3)          Linux Programmer’s Manual         PTHREAD_CANCEL(3)
NAME
       pthread_cancel - send a cancellation request to a thread
        //向一个线程发送取消请求

SYNOPSIS
       #include
         //包含头文件pthread.h

       int pthread_cancel(pthread_t thread);

       Compile and link with -pthread.
        //编译连接线程库

DESCRIPTION
       The  pthread_cancel()  function  sends  a cancellation request to the thread thread.  Whether and when the target thread reacts to the cancellation         request depends on two attributes that are under the control of that thread: its  cancelability state and type.
         //这个函数是向目标线程发送一个取消请求,目标线程会如何处理取消请求或者何时去处理都由它自己的属性来决定,线程的取消属性有取消类型
         // 取消状态

       A thread’s cancelability state, determined by pthread_setcancelstate(3), can be enabled (the default for new threads) or disabled.  If a thread has         disabled cancellation, then a cancellation request remains queued until  the  thread  enables cancellation.  If a thread has enabled cancellation, then         its cancelability type determines when cancellation occurs.
         //线程的取消状态是由函数 pthread_setcancelstate来设置的,可以设置为可取消(默认)或不可取消 。如果是不可取消状态,那么取消请求会一直
         // 发送直到目标线程变为可取消状态。如果线程是一个可取消的状态,那么取消类型决定了何时被取消

       A  thread’s  cancellation  type,  determined  by  pthread_setcanceltype(3),  may be either asynchronous or deferred (the default for new threads).        Asynchronous cancelability means that the thread can be canceled at any time (usually immediately,  but  the  system does not guarantee this).        Deferred cancelability means that cancellation will be delayed until the thread next calls a function that is a cancellation point.  A list of functions that        are  or  may  be  cancellation points is provided in pthreads(7).
         //一线线程的取消类型有函数 pthread_setcanceltype来修改,可以是异步的或者延时的(默认)。异步表示线程可以在任何时刻被取消(一般是立刻,
        //但操作系统不会确保永远这样)。延时取消代表取消操作会被延时直到下一个取消点。关于那些函数是取消点,你可以看手册man pthreads


       When a cancellation requested is acted on, the following steps occur for thread (in this order):     
        //一旦一个取消请求被响应了,那么以下的事情会发生

       1. Cancellation  clean-up  handlers are popped (in the reverse of the order in which they were pushed) and called.  (See
          pthread_cleanup_push(3).)
        //一个已经压栈的清除操作会被调用

       2. Thread-specific data destructors are called, in an unspecified order.  (See pthread_key_create(3).)
        //线程的特殊数据销毁程序会被调用,并且顺序不确定

       3. The thread is terminated.  (See pthread_exit(3).)
         //线程结束了

       The above steps happen asynchronously with respect to the pthread_cancel() call; the return status  of  pthread_cancel() merely informs the caller         whether the cancellation request was successfully queued.
         //以上的操作都会异步的执行, pthread_cancel() 的返回值会表示到底取消有没有成功
    
       After  a  canceled  thread has terminated, a join with that thread using pthread_join(3) obtains PTHREAD_CANCELED as the thread’s exit status.          (Joining with a thread is the only way to know that cancellation has completed.)
        //如果一个线程因为被取消而结束,那么如果有线程用pthread_join去连接它,那么 PTHREAD_CANCELED值会返回个这个join函数

RETURN VALUE
       On success, pthread_cancel() returns 0; on error, it returns a non-zero error number.
         //成功返回0,失败返回错误码

ERRORS
       ESRCH  No thread with the ID thread could be found.
        //找不到指定的线程

CONFORMING TO
       POSIX.1-2001.

NOTES
       On Linux, cancellation is implemented using signals.  Under the NPTL threading implementation, the first real-time  signal (i.e., signal 32) is used         for this purpose.  On LinuxThreads, the second real-time signal is used, if real-time signals are available, otherwise SIGUSR2 is used.
        //Linux的取消操作是用的信号的接口



PTHREAD_SETCANCELSTATE(3)  Linux Programmer’s Manual PTHREAD_SETCANCELSTATE(3)
NAME
       pthread_setcancelstate, pthread_setcanceltype - set cancelability state and type
        //设置取消状态和类型

SYNOPSIS
       #include
         //包含头文件

       int pthread_setcancelstate(int state, int *oldstate);
       int pthread_setcanceltype(int type, int *oldtype);

       Compile and link with -pthread.
        //编译连接使用线程库

DESCRIPTION
       The pthread_setcancelstate() sets the cancelability state of the calling thread to the value given in state.  The previous cancelability state of the         thread is returned in the buffer pointed to by oldstate.  The state  argument  must  have one of the following values:
        //这个函数可以设置线程的取消状态,之前的取消状态会返回到oldstate指定的缓冲区,取消状态只能是下面的值


       PTHREAD_CANCEL_ENABLE
              The  thread  is  cancelable.   This  is the default cancelability state in all new threads, including the initial thread.  The thread’s cancelability type               determines when a cancelable  thread  will  respond  to  a  cancellation request.
                //这个线程是可以取消的。这是一个线程默认的状态,包含初始化。线程的取消类型决定了线程何时响应取消请求

       PTHREAD_CANCEL_DISABLE
              The  thread  is  not  cancelable.   If  a  cancellation request is received, it is blocked until cancelability is enabled.
                 //这个线程是不可取消的。如果取消请求来了,它会阻塞,直到线程可以取消。

       The pthread_setcanceltype() sets the cancelability type of the calling thread to the value given in type.  The  previous cancelability  type  of  the         thread is returned in the buffer pointed to by oldtype.  The type argument must have one of the following values:
        // pthread_setcanceltype用来设置线程的取消类型。之前的取消类型会返回到oldtype指向的缓冲区,取消类型只能是一下的值

       PTHREAD_CANCEL_DEFERRED
              A cancellation request is deferred until the thread next calls a function  that  is  a  cancellation  point  (see pthreads(7)).  This is the default               cancelability type in all new threads, including the initial thread.
                 //取消请求被延时了,直到下一个取消点。
        
       PTHREAD_CANCEL_ASYNCHRONOUS
              The  thread  can be canceled at any time.  (Typically, it will be canceled immediately upon receiving a cancella-
              tion request, but the system doesn’t guarantee this.)
              //线程可以在任何时刻被取消(一般是立刻, 但操作系统不会确保永远这样

       The set-and-get operation performed by each of these functions is atomic with respect to other threads  in  the  process calling the same function.
        //这些set和get操作都是原子的
RETURN VALUE
       On success, these functions return 0; on error, they return a non-zero error number.
        //成功返回0,失败返回错误码

ERRORS
       The pthread_setcancelstate() can fail with the following error:
         //pthread_setcancelstate()会有以下错误码

       EINVAL Invalid value for state.
        //取消状态是无效的

       The pthread_setcanceltype() can fail with the following error:
         //pthread_setcanceltype()会有以下错误码

       EINVAL Invalid value for type.
        //取消类型是无效的

CONFORMING TO
       POSIX.1-2001.


NOTES
       For details of what happens when a thread is canceled, see pthread_cancel(3).
        //要知道取消到底会发生什么,请看手册 pthread_cancel

       Briefly  disabling  cancelability  is useful if a thread performs some critical action that must not be interrupted by acancellation request.  Beware
       of disabling cancelability for long periods, or around operations that may block for  long periods, since that will render the thread unresponsive
      to cancellation requests.


       Setting  the  cancelability type to PTHREAD_CANCEL_ASYNCHRONOUS is rarely useful.  Since the thread could be canceled at any time, it
      cannot  safely reserve resources (e.g., allocating memory with malloc(3)), acquire mutexes,  semaphores,  or locks,  and  so on.  Reserving
      resources is unsafe because the application has no way of knowing what the state of these resources is when the thread is canceled; that is,
      did cancellation occur before the resources were reserved, while they were  reserved,  or after they were released?  Furthermore, some internal
      data structures(e.g., the linked list of free blocks managed by the malloc(3) family of functions) may be left in an inconsistent state if cancellation
       occurs in  the middle  of  the  function call.  Consequently, clean-up handlers cease to be useful.  Functions that can be safely asynchronously
       canceled  are  called  async-cancel-safe  functions.   POSIX.1-2001  only  requires  that  pthread_cancel(3), pthread_setcancelstate(),  and  
      pthread_setcanceltype() be async-cancel-safe.  In general, other library functions can’t be safely called from an asynchronously cancelable thread.  
      One of the few  circumstances in which asynchronous  cancelability is useful is for cancellation of a thread that is in a pure compute-bound loop.

       The  Linux  threading implementations permit the oldstate argument of pthread_setcancelstate() to be NULL, in which case the information about
      the previous cancelability state is not returned to the caller.  Many other  implementations  also permit  a  NULL  oldstat  argument, but POSIX.1-
       2001 does not specify this point, so portable applications should always specify a non-NULL value in oldstate.  A precisely analogous set of
       statements applies  for  the  oldtype  argument  of pthread_setcanceltype().

七、实例
    1、程序框架 
    2、源代码

点击(此处)折叠或打开

  1. /*`DATE: 2015-3-26
  2.  *AUTHOR:WJ
  3.  *
  4.  *int pthread_cancle(pthread_t tid)
  5.  * 取消tid指定的线程,成功返回0。但是取消只是发送一个请求,
  6.  * 并不意味着等待线程终止,而且发送成功也不意味着tid一定会终止
  7.  *int pthread_setcancelstate(int state, int *oldstate)
  8.  * 设置本线程对Cancel信号的反应,state有两种值:PTHREAD_CANCEL_ENABLE(缺省)
  9.  * 和PTHREAD_CANCEL_DISABLE,分别表示收到信号后设为CANCLED状态和忽略CANCEL信
  10.  * 号继续运行;old_state如果不为NULL则存入原来的Cancel状态以便恢复。
  11.  *int pthread_setcanceltype(int type, int *oldtype)
  12.  *     设置本线程取消动作的执行时机,type由两种取值:PTHREAD_CANCEL_DEFFERED和
  13.  *     PTHREAD_CANCEL_ASYNCHRONOUS,仅当Cancel状态为Enable时有效,分别表示收到信号
  14.  *     后继续运行至下一个取消点再退出和立即执行取消动作(退出);oldtype如果不为NULL
  15.  *     则存入运来的取消动作类型值。
  16.  */

  17. #include "apue.h"

  18. void *thread_fun(void *arg)
  19. {
  20.     int stateval;
  21.     int typeval;
  22.     stateval = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
  23.     if(stateval != 0)
  24.     {
  25.         printf("set cancel state failed\n");
  26.     }
  27.     printf("Im new thread\n");
  28.     sleep(4);


  29.     printf("about to cancel \n");
  30.     stateval = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
  31.     if(stateval != 0)
  32.     {
  33.         printf("set cancel state failed\n");
  34.     }
  35.     typeval = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
  36.     if(typeval != 0)
  37.     {
  38.         printf("set cancel type failed\n");
  39.     }
  40.     
  41.     printf("first cancel point\n");
  42.     printf("second cancel point\n");

  43.     return (void *)20;
  44. }

  45. int main()
  46. {
  47.     pthread_t tid ;
  48.     int err, cval, jval;
  49.     void *rval;

  50.     err = pthread_create(&tid, NULL, thread_fun, NULL);
  51.     if(err != 0)
  52.     {
  53.         printf("create thread failed\n");
  54.         return 0;
  55.     }
  56.     sleep(2);

  57.     cval = pthread_cancel(tid);
  58.     if(cval != 0)
  59.     {
  60.         printf("cancel thread failed\n");
  61.     }
  62.     jval = pthread_join(tid, &rval);
  63.     
  64.     printf("new thread exit code is %d\n", (int *)rval);

  65.     return 0;
  66. }
    3、练习:证明线程可以自己取消自己

点击(此处)折叠或打开

  1. /*DATE:        2015-3-25
  2.  *AUTHOR:        WJ
  3.  *DESCRIPTION: 一个新线程自己可以取消自己
  4.  *    int pthread_cancel(pthread_t tid)
  5.  *    取消tid指定的线程,成功返回0。但是取消只是发送一个请求,并不意味着等待线程终止,而且发送成功也不意味着tid一定会终止
  6.  *    int pthread_setcancelstate(int state, int *oldstate)
  7.  *    设置本线程对Cancel信号的反应,state有两种值:PTHREAD_CANCEL_ENABLE(缺省)和PTHREAD_CANCEL_DISABLE,
  8.  *    int pthread_setcanceltype(int type, int *oldtype)
  9.  *    设置本线程取消动作的执行时机,type由两种取值:PTHREAD_CANCEL_DEFFERED和PTHREAD_CANCEL_ASYCHRONOUS,仅当Cancel状态为Enable时有效,分别表示收到
  10.  *    信号后继续运行至下一个取消点再退出和立即执行取消动作(退出);oldtype如果不为NULL则存入运来的取消动作类型值。
  11.  */
  12. #include "apue.h"

  13. int err;
  14. pthread_t tid;

  15. void *thread_fun(void *arg)
  16. {
  17.     printf("I'm new thread\n");

  18.     printf("I'm about to cancel myself\n");
  19.     //设置取消类型为延时取消
  20.     pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
  21.     //设置取消状态为可以取消
  22.     pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
  23.     //取消自己
  24.     err = pthread_cancel(pthread_self());
  25.     if(err == 0)
  26.     {
  27.         printf("cancel myself success\n");
  28.     }
  29.     printf("cancel myself failed\n");
  30.     
  31.     pthread_exit((void *)0);
  32. }


  33. int main()
  34. {
  35.     //创造新线程
  36.     err = pthread_create(&tid, NULL, thread_fun, NULL);
  37.     if(err != 0)
  38.     {
  39.         printf("create new thread1 failed\n");
  40.         return 0;
  41.     }

  42.     err = pthread_join(tid, NULL);
  43.     if(err != 0)
  44.     {
  45.         printf("main thread join new thread failed\n");
  46.     }
  47.     else
  48.     {
  49.         printf("main thread join new thread success\n");
  50.     }
  51.     return 0;
  52. }

相关文章
|
10天前
|
存储 Java 数据库连接
java多线程之线程通信
java多线程之线程通信
|
17天前
|
Linux C++
LInux下Posix的传统线程示例
LInux下Posix的传统线程示例
15 1
|
21天前
|
存储 缓存 NoSQL
Redis单线程已经很快了6.0引入多线程
Redis单线程已经很快了6.0引入多线程
31 3
|
24天前
|
消息中间件 安全 Linux
线程同步与IPC:单进程多线程环境下的选择与权衡
线程同步与IPC:单进程多线程环境下的选择与权衡
57 0
|
24天前
|
算法 Unix Linux
Linux与Qt线程优先级的对应关系:一次全面解析
Linux与Qt线程优先级的对应关系:一次全面解析
21 0
|
25天前
|
消息中间件 Linux 调度
【Linux 进程/线程状态 】深入理解Linux C++中的进程/线程状态:阻塞,休眠,僵死
【Linux 进程/线程状态 】深入理解Linux C++中的进程/线程状态:阻塞,休眠,僵死
65 0
|
17天前
|
安全 Java 容器
Java并发编程:实现高效、线程安全的多线程应用
综上所述,Java并发编程需要注意线程安全、可见性、性能等方面的问题。合理使用线程池、同步机制、并发容器等工具,可以实现高效且线程安全的多线程应用。
14 1
|
23天前
|
监控 Linux 调度
【Linux 应用开发 】Linux 下应用层线程优先级管理解析
【Linux 应用开发 】Linux 下应用层线程优先级管理解析
41 0
|
24天前
|
存储 算法 Linux
【Linux 系统标准 进程资源】Linux 创建一个最基本的进程所需的资源分析,以及线程资源与之的差异
【Linux 系统标准 进程资源】Linux 创建一个最基本的进程所需的资源分析,以及线程资源与之的差异
25 0
|
1月前
|
Java 调度 C#
C#学习系列相关之多线程(一)----常用多线程方法总结
C#学习系列相关之多线程(一)----常用多线程方法总结