使用 pthread_cancel 取消线程:好习惯还是坏习惯
- 2024-10-21 09:14:00
- admin 原创
- 98
问题描述:
我在 Linux(CentOS 5.3)上有一个 C++ 程序,它生成多个线程,这些线程处于无限循环中以执行作业并休眠几分钟。现在,我必须取消正在运行的线程,以防出现新的配置通知并重新启动一组新线程,为此我使用了 pthread_cancel。我观察到,即使收到取消指示后线程也不会停止,甚至一些休眠线程在休眠完成后也会启动。
由于这种行为不是我们所期望的,在上述场景中使用 pthread_cancel 引发了人们对其是好是坏的疑问。
请评论上述场景中 pthread_cancel 的使用情况。
解决方案 1:
一般来说,取消线程并不是一个好主意。只要有可能,最好有一个共享标志,供线程用来跳出循环。这样,你就可以让线程在实际退出之前执行它们可能需要做的任何清理工作。
关于线程实际上没有取消的问题,POSIX 规范确定了一组取消点 ( man 7 pthreads )。线程只能在这些点被取消。如果您的无限循环不包含取消点,您可以通过调用来添加一个pthread_testcancel
。如果pthread_cancel
已被调用,那么它将在此时执行。
解决方案 2:
如果您正在编写异常安全的 C++ 代码(请参阅http://www.boost.org/community/exception_safety.html),那么您的代码自然就可以取消线程了。glibs在线程取消时抛出 C++ 异常,以便您的析构函数可以进行适当的清理。
解决方案 3:
您可以执行与以下代码等效的操作。
#include <pthread.h>
#include <cxxabi.h>
#include <unistd.h>
...
void *Control(void* pparam)
{
try
{
// do your work here, maybe long loop
}
catch (abi::__forced_unwind&)
{ // handle pthread_cancel stack unwinding exception
throw;
}
catch (exception &ex)
{
throw ex;
}
}
int main()
{
pthread_t tid;
int rtn;
rtn = pthread_create( &tid, NULL, Control, NULL );
usleep(500);
// some other work here
rtn = pthtead_cancel( tid );
}
解决方案 4:
我会使用 boost::asio。
类似于:
struct Wait {
Wait() : timer_(io_service_), run_(true) {}
boost::asio::io_service io_service_;
mutable boost::asio::deadline_timer timer_;
bool run_;
};
void Wait::doWwork() {
while (run) {
boost::system::error_code ec;
timer_.wait(ec);
io_service_.run();
if (ec) {
if (ec == boost::asio::error::operation_aborted) {
// cleanup
} else {
// Something else, possibly nasty, happened
}
}
}
}
void Wait::halt() {
run_ = false;
timer_.cancel();
}
一旦你理解了它,你就会发现 asio 是一个非常棒的工具。
相关推荐
热门文章
项目管理软件有哪些?
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件
热门标签
云禅道AD