一、线程取消 将正在运行的线程取消执行,一个线程可以取消另一个线程,线程也可以自己取消自己。当线程被取消之后,会调用清理函数
二、取消函数 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.
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、源代码
- /*`DATE: 2015-3-26
- *AUTHOR:WJ
- *
- *int pthread_cancle(pthread_t tid)
- * 取消tid指定的线程,成功返回0。但是取消只是发送一个请求,
- * 并不意味着等待线程终止,而且发送成功也不意味着tid一定会终止
- *int pthread_setcancelstate(int state, int *oldstate)
- * 设置本线程对Cancel信号的反应,state有两种值:PTHREAD_CANCEL_ENABLE(缺省)
- * 和PTHREAD_CANCEL_DISABLE,分别表示收到信号后设为CANCLED状态和忽略CANCEL信
- * 号继续运行;old_state如果不为NULL则存入原来的Cancel状态以便恢复。
- *int pthread_setcanceltype(int type, int *oldtype)
- * 设置本线程取消动作的执行时机,type由两种取值:PTHREAD_CANCEL_DEFFERED和
- * PTHREAD_CANCEL_ASYNCHRONOUS,仅当Cancel状态为Enable时有效,分别表示收到信号
- * 后继续运行至下一个取消点再退出和立即执行取消动作(退出);oldtype如果不为NULL
- * 则存入运来的取消动作类型值。
- */
-
- #include "apue.h"
-
- void *thread_fun(void *arg)
- {
- int stateval;
- int typeval;
- stateval = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
- if(stateval != 0)
- {
- printf("set cancel state failed\n");
- }
- printf("Im new thread\n");
- sleep(4);
-
-
- printf("about to cancel \n");
- stateval = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
- if(stateval != 0)
- {
- printf("set cancel state failed\n");
- }
- typeval = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
- if(typeval != 0)
- {
- printf("set cancel type failed\n");
- }
-
- printf("first cancel point\n");
- printf("second cancel point\n");
-
- return (void *)20;
- }
-
- int main()
- {
- pthread_t tid ;
- int err, cval, jval;
- void *rval;
-
- err = pthread_create(&tid, NULL, thread_fun, NULL);
- if(err != 0)
- {
- printf("create thread failed\n");
- return 0;
- }
- sleep(2);
-
- cval = pthread_cancel(tid);
- if(cval != 0)
- {
- printf("cancel thread failed\n");
- }
- jval = pthread_join(tid, &rval);
-
- printf("new thread exit code is %d\n", (int *)rval);
-
- return 0;
- }
3、练习:证明线程可以自己取消自己
- /*DATE: 2015-3-25
- *AUTHOR: WJ
- *DESCRIPTION: 一个新线程自己可以取消自己
- * int pthread_cancel(pthread_t tid)
- * 取消tid指定的线程,成功返回0。但是取消只是发送一个请求,并不意味着等待线程终止,而且发送成功也不意味着tid一定会终止
- * int pthread_setcancelstate(int state, int *oldstate)
- * 设置本线程对Cancel信号的反应,state有两种值:PTHREAD_CANCEL_ENABLE(缺省)和PTHREAD_CANCEL_DISABLE,
- * int pthread_setcanceltype(int type, int *oldtype)
- * 设置本线程取消动作的执行时机,type由两种取值:PTHREAD_CANCEL_DEFFERED和PTHREAD_CANCEL_ASYCHRONOUS,仅当Cancel状态为Enable时有效,分别表示收到
- * 信号后继续运行至下一个取消点再退出和立即执行取消动作(退出);oldtype如果不为NULL则存入运来的取消动作类型值。
- */
- #include "apue.h"
-
- int err;
- pthread_t tid;
-
- void *thread_fun(void *arg)
- {
- printf("I'm new thread\n");
-
- printf("I'm about to cancel myself\n");
- //设置取消类型为延时取消
- pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
- //设置取消状态为可以取消
- pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
- //取消自己
- err = pthread_cancel(pthread_self());
- if(err == 0)
- {
- printf("cancel myself success\n");
- }
- printf("cancel myself failed\n");
-
- pthread_exit((void *)0);
- }
-
-
- int main()
- {
- //创造新线程
- err = pthread_create(&tid, NULL, thread_fun, NULL);
- if(err != 0)
- {
- printf("create new thread1 failed\n");
- return 0;
- }
-
- err = pthread_join(tid, NULL);
- if(err != 0)
- {
- printf("main thread join new thread failed\n");
- }
- else
- {
- printf("main thread join new thread success\n");
- }
- return 0;
- }