我想用它的线程对象杀死一个std :: thread?

CPS*_*CPS 29 c++ multithreading std c++11 stdthread

可能重复:
C++ 0x线程中断

我试图通过使用其线程对象来杀死/停止c ++ std :: thread.

我们应该怎么做?

Mat*_* M. 41

@ bamboon的答案很好,但我觉得这应该得到更强有力的声明.

无论您使用何种语言,您的程序都将获取并释放资源:内存,文件描述符......对于一次性触发的简单程序,泄漏资源并不重要:当程序结束时,现代操作系统会自动恢复资源; 但是对于长期运行的程序,基本要求不是泄漏资源,或者至少不重复.

因此,您应该从一开始就被教导,当您获得资源时,您必须确保它在某一时刻被释放:

void foo(int i) {
    int* array = malloc(sizeof(int) * i);

    /* do something */

    free(array);
}
Run Code Online (Sandbox Code Playgroud)

所以,问问自己这个问题:

  • 当我杀死程序时会发生什么?
  • 当我杀死线程时会发生什么?

好吧,正如我们所说的,当一个程序结束时,操作系统会收回资源,所以假设(并且这是一些假设)你没有在另一个系统上获得资源,或者这个系统得到了很好的保护,免受这种滥用,没有坏处,没有犯规.

但是,当您终止某个线程时,该程序仍会运行,因此操作系统不会收回资源.你忘记了内存,你锁定了一个文件写作你再也无法解锁了...... 你不应该杀死线程.

更高级别的语言有办法解决这个问题:例外.因为程序应该是异常安全的,所以Java(例如)会通过暂停它来杀死一个线程,在执行时抛出一个异常,然后轻轻地展开堆栈.但是,C++中还没有这样的功能.

这不可能吗?不,显然不是.实际上,你可以完全重用同样的想法:

  • encapsulate std::thread,interruptible_threadclass也将包含一个中断标志
  • 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
Run Code Online (Sandbox Code Playgroud)

现在,您可以在适当的位置撒上线程代码并检查中断.

  • +1,**这**是一个如此重要的概念.线程是处理的不同资源和安全域.他们需要合作而不是"对抗"的方法.重构代码,以便线程可以在请求时正常终止. (6认同)
  • @JonathanWakely:对不起,误读了。我的观点是异常是语言中的*正常*机制,因此您可以以*正常*的方式满足它们:`try/catch`块,RAII等......而残酷的中断使您无法清理向上。请注意,我说*在适当的地方**检查中断**。*!而且你仍然可以中断 foo,只要你捕捉到异常以便执行 `free` ......但这并不是真正的意思,我更多地炫耀了对清理的需求 *明确* 而构建良好的 C++程序将使用 RAII,显然。 (2认同)

inf*_*inf 28

你不能.

std::threads是不可中断的.您可以使用boost::thread哪个提供此功能.

Boost通过定义"中断点"来做到这一点,如果线程被中断并且达到这样一个点,线程将在该中断点上结束.

然而,大多数时候考虑重新设计可能是达到你想要实现的目标的最简洁和最简单的方法.

如果您仍在寻找可中断线程的C++ 11实现,请查看Anthony Williams(提升线程的所有者)的书"C++ Concurrency in Action".他经历了如何实现这一目标的基本实现.

std::thread::native_handle 允许您访问可能支持中断的平台特定底层线程句柄,但是这种方法使您的代码不可移植,并且可能在任何方面都不干净.