提问人:CPS 提问时间:12/15/2012 最后编辑:CommunityCPS 更新时间:9/15/2019 访问量:60081
我想使用它的线程对象杀死一个 std::thread?[复制]
I want to kill a std::thread using its thread object? [duplicate]
答:
你不能。
std::threads
是不可中断的。您可以使用提供此功能的。boost::thread
Boost 通过定义“中断点”来实现这一点,如果线程被中断并达到这样的点,线程将在该中断点上结束。
然而,大多数时候,考虑重新设计可能是达到您想要实现的目标的最干净和最简单的方法。
如果你还在寻找可中断线程的C++11实现,请查看Anthony Williams(boost线程的所有者)的书“C++并发在行动”。他经历了如何实现这样的事情的基本实现。
std::thread::native_handle
使您可以访问特定于平台的底层线程句柄,该句柄可能支持中断,但是这种方法会使您的代码不可移植,并且可能在任何方面都不会更干净。
评论
@bamboon的回答很好,但我觉得这值得一个更有力的声明。
无论您使用哪种语言,您的程序都将获取和释放资源:内存、文件描述符......对于一次性启动的简单程序,泄漏资源并不重要:当程序结束时,现代操作系统会自动收回资源;但是,对于长时间运行的程序,基本要求是不要泄漏资源,或者至少不要重复。
因此,您应该从一开始就被教导,当您获得资源时,您必须确保它在某一时刻被释放:
void foo(int i) {
int* array = malloc(sizeof(int) * i);
/* do something */
free(array);
}
所以,问自己一个问题:
- 当我杀死程序时会发生什么?
- 当我杀死线程时会发生什么?
好吧,正如我们所说,当一个程序结束时,操作系统会收集资源,所以假设(这是一些假设)你没有在另一个系统上获得资源,或者这个系统得到了很好的保护,免受这种滥用,没有伤害,没有犯规。
但是,当您终止线程时,程序仍会运行,因此操作系统不会重新收集资源。你泄漏了内存,你锁定了一个你无法再解锁的文件进行写入,......你不应该杀死线程。
高级语言有一种方法可以处理这个问题:异常。因为程序无论如何都应该是异常安全的,所以 Java(例如)会通过暂停线程来终止线程,在执行点抛出异常,然后轻轻地展开堆栈。但是,C++中还没有这样的设施。
不可能吗?不,显然不是。实际上,您可以完美地重用相同的想法:
- encapsulate ,class 还将包含一个中断标志
std::thread
interruptible_thread
- 在启动标志时将标志的地址传递给它,并以线程本地的方式存储它
std::thread
- 使用检查点检测代码,检查是否设置了中断标志,以及何时引发异常
那是:
// Synopsis
class interrupt_thread_exception;
class interruptible_thread;
void check_for_interrupt();
// Interrupt exception
class interrupt_thread_exception: public virtual std::exception {
public:
virtual char const* what() const override { return "interrupt"; }
}; // class interrupt_thread_exception
// Interruptible thread
class interruptible_thread {
public:
friend void check_for_interrupt();
template <typename Function, typename... Args>
interruptible_thread(Function&& fun, Args&&... args):
_thread([](std::atomic_bool& f, Function&& fun, Args&&... args) {
_flag_ref = &f; fun(std::forward<Args>(args)...);
},
_flag,
std::forward<Function>(fun),
std::forward<Args>(args)...)
{}
bool stopping() const { return _flag.load(); }
void stop() { _flag.store(true); }
private:
static thread_local std::atomic_bool* _flag_ref = nullptr;
std::atomic_bool _flag = false;
std::thread _thread;
}; // class interruptible_thread
// Interruption checker
inline void check_for_interrupt() noexcept(false) {
if (not interruptible_thread::_flag_ref) { return; }
if (not interruptible_thread::_flag_ref->load()) { return; }
throw interrupt_thread_exception();
} // check_for_interrupt
现在,您可以在适当的位置对线程代码进行中断检查。
评论
void foo(int)
已经不是例外安全了,如果你在“/* 做某事 */”中间有一个中断检查,它仍然是错误的。
try/catch
free
terminate()
getline
评论