linux线程取消, pthread线程取消,pthread_testcancel用法

32 篇文章 3 订阅
8 篇文章 0 订阅

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

  • 24
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
pthread_testcancel 和 pthread_cancel 是多线程编程中用于线程交互的两个重要函数,它们可以协调多个线程的执行,实现线程的安全退出和资源释放。 下面是 pthread_testcancel 和 pthread_cancel线程交互模型: 1. 主线程创建一个新线程,并向新线程发送取消请求,同时将新线程取消状态设置为 PTHREAD_CANCEL_ENABLE,以确保新线程可以响应取消请求。 2. 新线程在执行任务时,不断使用 pthread_testcancel 函数检测是否收到取消请求,如果收到了取消请求,就立即退出线程函数。 3. 如果新线程正在阻塞等待或者 sleep 等待,那么就会立即响应取消请求,退出阻塞状态或者 sleep 等待,然后立即退出线程函数。 4. 如果新线程没有收到取消请求,就会继续执行任务,直到任务完成或者收到取消请求为止。 5. 如果主线程需要取消线程的执行,可以调用 pthread_cancel 函数向新线程发送取消请求,让新线程在适当的时候退出执行。 6. 如果新线程没有及时响应取消请求,那么就会出现线程无法退出的情况,从而导致资源泄露和程序异常等问题。 7. 在编写多线程程序时,需要注意线程安全性和取消操作的使用,避免竞争条件和死锁等问题,确保程序能够正确安全地运行。 总之,pthread_testcancel 和 pthread_cancel 是多线程编程中用于线程交互的两个重要函数,它们可以协调多个线程的执行,实现线程的安全退出和资源释放。在多线程编程中,需要注意线程安全性和取消操作的使用,避免竞争条件和死锁等问题,确保程序能够正确安全地运行。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值