pthread_cancel
Linux中,线程在运行时如果想要取消,一种方法是调用pthread_cancel()函数,它的原型是:
/* Cancel THREAD immediately or at the next possibility. */
extern int pthread_cancel (pthread_t __th);
参数pthread_t __th表示线程的id。
它的使用方法如下,
示例1
#include <stdio.h>
#include <pthread.h>
#include <sys/time.h>
#include <unistd.h>
void* thread_func(void* arg)
{
int count = 0;
while(1) {
printf("Thread is running, count: %d\n", count);
count++;
sleep(5);
}
printf("this is a thread cancel test 111\n");
sleep(1);
printf("test 222\n");
printf("Thread cancellation requested. Exiting...\n");
pthread_exit(NULL);
return NULL;
}
int main()
{
pthread_t thread;
pthread_create(&thread, NULL, thread_func, NULL);
sleep(3);
pthread_cancel(thread);
pthread_join(thread, NULL);
printf("Thread canceled successfully.\n");
sleep(6);
printf("end\n");
return 0;
}
gcc -o threadcancel threadcancel.cpp -lpthread
输出为:
Thread is running, count: 0
Thread canceled successfully.
end
程序启动后会启动线程,线程执行while循环,在第一个循环中等待5秒。同时,main函数继续执行,在睡眠3秒后调用pthread_cancel。此时线程还在5秒睡眠中,它直接停止。
注意,while(1)循环后面的printf("this is a thread cancel test 111\n");及以后的内容都没有执行。
示例2
线程停止是在调用pthread_cancel立即停止吗,从上面看是的,我们在用其他示例验证一下:
#include <stdio.h>
#include <pthread.h>
#include <sys/time.h>
#include <unistd.h>
void* thread_func(void* arg)
{
int count = 0;
while(count < 2) {
printf("Thread is running, count: %d\n", count);
count++;
sleep(1);
}
printf("this is a thread cancel test 111\n");
sleep(5);
printf("test 222\n");
printf("Thread cancellation requested. Exiting...\n");
pthread_exit(NULL);
return NULL;
}
int main()
{
pthread_t thread;
pthread_create(&thread, NULL, thread_func, NULL);
sleep(3);
pthread_cancel(thread);
pthread_join(thread, NULL);
printf("Thread canceled successfully.\n");
sleep(6);
printf("end\n");
return 0;
}
注意,这里的线程thread中的循环时间变了,从代码上看,调用pthread_cancel时,线程thread正处于睡眠5秒的时候,那么printf("this is a thread cancel test 111\n");应该会执行。
程序输出:
Thread is running, count: 0
Thread is running, count: 1
this is a thread cancel test 111
Thread canceled successfully.
end
这证明线程在调用pthread_cancel后立即停止。
疑问:什么样的线程都能被取消吗?
我开始以为是的,后来发现不是,比如下面的写法:
示例3
#include <stdio.h>
#include <pthread.h>
#include <sys/time.h>
#include <unistd.h>
void* thread_func(void* arg)
{
int count = 0;
while(1) {
count++;
}
printf("this is a thread cancel test 111\n");
pthread_testcancel();
printf("test 222\n");
printf("Thread cancellation requested. Exiting...\n");
pthread_exit(NULL);
return NULL;
}
int main()
{
pthread_t thread;
pthread_create(&thread, NULL, thread_func, NULL);
usleep(1);
pthread_cancel(thread);
printf("call pthread_cancel.\n");
pthread_join(thread, NULL);
printf("Thread canceled successfully.\n");
printf("end\n");
return 0;
}
函数是一个死循环,运行的结果为:
call pthread_cancel.
然后就卡在那里。
调用pthread_cancel并没有成功。
后来我在这篇文章中关于pthread_cancel()的运用,取消点的理解-CSDN博客,明白了函数取消点的含义:
取消点:
我们都知道,程序的进行是一个时间过程而不是一个时间点。取消点的简单意思来说:
在一个时间段内,程序被挂起时,可以被取消的一个时间点。(APUE363页有详细的取消点函数)
也就是说,当线程出现 block(阻塞) 时,这个被阻塞的地方就是可被取消的地方。
更通俗的来说:就是线程A执行过程中,如果遇到其他线程B执行cancel函数,
线程继续运行,直到线程某一行代码出现阻塞
(如:pthread_testcancel、pthread_join、pthread_cond_wait、printf、sleep、read、write、等都是可以产生阻塞的函数)
此时就会退出。如果线程B还使用了pthread_join去获取返回值,返回值为整型且为PTHREAD_CANCELED(-1)
————————————————
版权声明:本文为CSDN博主「ySh_ppp」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ySh_lC/article/details/120310393
如果函数中没有取消点,或者还没有运行到取消点,那就不会取消,就像上面程序那样。这些具有取消点功能的函数可以理解为系统调用,如果没有这些函数,就要手动加一个pthread_testcancel作为取消点。
pthread_testcancel
设置线程函数取消点,它的原型如下:
/* Test for pending cancellation for the current thread and terminate
the thread as per pthread_exit(PTHREAD_CANCELED) if it has been
cancelled. */
extern void pthread_testcancel (void);
示例4
#include <stdio.h>
#include <pthread.h>
#include <sys/time.h>
#include <unistd.h>
void* thread_func(void* arg)
{
int count = 0;
while(1) {
count++;
pthread_testcancel();
}
printf("this is a thread cancel test 111\n");
pthread_testcancel();
printf("test 222\n");
printf("Thread cancellation requested. Exiting...\n");
pthread_exit(NULL);
return NULL;
}
int main()
{
pthread_t thread;
pthread_create(&thread, NULL, thread_func, NULL);
usleep(1);
pthread_cancel(thread);
printf("call pthread_cancel.\n");
pthread_join(thread, NULL);
printf("Thread canceled successfully.\n");
printf("end\n");
return 0;
}
输出为:
call pthread_cancel.
Thread canceled successfully.
end
可以取消成功了。
不让线程被取消
如果不想让线程被取消,需要将线程设置为:
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
则pthread_testcancel和其他的系统调用就失灵了。
函数pthread_setcancelstate是可以改变线程遇到cancel信号的状态。
一共有两种状态:
1、对cancel信号有反应(默认):PTHREAD_CANCEL_ENABLE
2、不理会cancel信号 :PTHREAD_CANCEL_DISABLE
示例5
#include <stdio.h>
#include <pthread.h>
#include <sys/time.h>
#include <unistd.h>
void* thread_func(void* arg)
{
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
int count = 0;
while(1) {
count++;
pthread_testcancel();
}
printf("this is a thread cancel test 111\n");
pthread_testcancel();
printf("test 222\n");
printf("Thread cancellation requested. Exiting...\n");
pthread_exit(NULL);
return NULL;
}
int main()
{
pthread_t thread;
pthread_create(&thread, NULL, thread_func, NULL);
usleep(1);
pthread_cancel(thread);
printf("call pthread_cancel.\n");
pthread_join(thread, NULL);
printf("Thread canceled successfully.\n");
printf("end\n");
return 0;
}
输出为:call pthread_cancel.
程序卡住,不会被取消。
取消std::thread
std::thread也可以使用pthread_cancel取消,示例如下:
#include <stdio.h>
#include <thread>
#include <pthread.h>
#include <sys/time.h>
#include <unistd.h>
#include <iostream>
using namespace std;
void func()
{
int count = 0;
while(1) {
printf("Thread is running, count: %d\n", count);
count++;
pthread_testcancel();
sleep(2);
}
printf("this is a thread cancel test 111\n");
printf("test 222\n");
printf("Thread cancellation requested. Exiting...\n");
pthread_exit(NULL);
}
int main()
{
std::thread testThread(&func);
sleep(3);
pthread_cancel((pthread_t)testThread.native_handle());
printf("call pthread_cancel.\n");
testThread.join();
printf("Thread canceled successfully.\n");
printf("end\n");
return 0;
}
运行结果:
Thread is running, count: 0
Thread is running, count: 1
call pthread_cancel.
Thread canceled successfully.
end
文章知识点与官方知
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/gdizcm/article/details/135178858