C++ 0x线程中断

Nic*_*lli 56 c++ multithreading c++11

根据C++ 0x最终草案,没有办法请求线程终止.也就是说,如果需要,我们需要实施一个自己动手的解决方案.

另一方面,boost :: thread提供了一种以安全方式中断线程的机制.

在您看来,什么是最好的解决方案?设计自己的合作"中断机制"还是本土的?

pet*_*hen 16

所有语言规范都表示支持不是内置于语言中. boost::thread::interrupt还需要线程函数的一些支持:

当被中断的线程接下来执行一个指定的中断点时(或者当执行一个时当前被阻塞)

即当线程函数没有给调用者中断的机会时,你仍然被卡住了.

我不确定你对"原住民"的意思 - 没有原生支持,除非你被迷住了boost:threads.

不过,我还是会使用一种明确的机制.无论如何你必须考虑有足够的中断点,为什么不明确它们?根据我的经验,额外的代码通常是微不足道的,尽管您可能需要将一些等待从单个对象更改为多个对象,这取决于您的库 - 可能看起来更加丑陋.


人们也可以提出"不要使用控制流程的例外",但与线程相比,这只是一个指导原则.


Vic*_*iba 10

使用本机句柄取消线程是C++中的一个错误选项,因为您需要销毁所有堆栈分配的对象.这是他们不包括取消操作的主要原因.

Boost.Thread提供了一种中断机制,需要在任何等待的原语上进行池化.由于这作为一般机制可能是昂贵的,因此该标准未包括它.

您需要自己实现它.请在此处查看我的答案,了解如何自行实现此问题.要完成解决方案,当中断为真时,应该抛出中断,并且线程应该捕获此中断并完成.


use*_*543 6

由于你无法控制任何数据结构的状态,因此终止一个线程是不安全的.

如果要中断正在运行的线程,则必须实现自己的机制.恕我直言,如果您需要,您的设计不适合多线程.

如果您只想等待线程完成,请使用join()或future.

  • 中断正在运行的线程有很多理由,这些并不意味着设计不好. (54认同)
  • -1,你完全忽略了*way*在boost中实现了中断.这是一种确定性方法,涉及从某些预定义点抛出异常.异常安全保证了线程正在处理的数据的完整性. (28认同)
  • 我同意Chris O. (6认同)
  • 例如:在启发式算法中,可能有多个线程在不同的空间中搜索解决方案.一旦一个线程找到解决方案,其他线程就会被杀死或取消.好的,我同意我们也可以手工编写它,但它看起来像一个基本要求. (6认同)

Mar*_*tos 6

由于整个过程的状态在该点之后变得不确定,因此抢先终止线程是不安全的.该线程可能在被终止之前获得了一个关键部分.现在永远不会释放那个关键部分.堆可能会永久锁定,依此类推.

boost::thread::interrupt解决方案可通过询问很好.它只会中断线程执行可中断的操作,比如等待Boost.Thread条件变量,或者如果线程在调用中断后执行其中一项操作.即便如此,线程并没有被毫不客气地通过绞肉机,比如,Win32的TerminateThread功能,它只会引发异常,如果你是一个表现良好的编码器并且在任何地方使用RAII,它将会自行清理并优雅地退出线程.


Mic*_*yan 5

实现自己动手解决方案最有意义,而且真的不应该那么难.您将需要一个同步读/写的共享变量,指示是否要求该线程终止,并且当该变量处于可以安全中断的状态时,您的线程会定期从该变量读取.如果要中断某个线程,只需同步写入该变量,然后加入该线程即可.假设它适当地协作,它应该注意到变量已被写入并关闭,导致连接函数不再阻塞.

如果你是土生土长的,你就不会得到任何东西; 您只需抛弃标准和跨平台OOP线程机制的所有好处.为了使您的代码正确,线程需要合作关闭,这意味着上述通信.


dim*_*tri 5

这是我对线程取消器的简单实现(对于C++ 0x).我希望它会有用.

// Class cancellation_point
#include <mutex>
#include <condition_variable>

struct cancelled_error {};

class cancellation_point
{
public:
    cancellation_point(): stop_(false) {}

    void cancel() {
        std::unique_lock<std::mutex> lock(mutex_);
        stop_ = true;
        cond_.notify_all();
    }

    template <typename P>
    void wait(const P& period) {
        std::unique_lock<std::mutex> lock(mutex_);
        if (stop_ || cond_.wait_for(lock, period) == std::cv_status::no_timeout) {
            stop_ = false;
            throw cancelled_error();
        }
    }
private:
    bool stop_;
    std::mutex mutex_;
    std::condition_variable cond_;
};


// Usage example
#include <thread>
#include <iostream>

class ThreadExample
{
public:
    void start() {
        thread_ = std::unique_ptr<std::thread>(
            new std::thread(std::bind(&ThreadExample::run, this)));
    }
    void stop() {
        cpoint_.cancel();
        thread_->join();
    }
private:
    void run() {
        std::cout << "thread started\n";
        try {
            while (true) {
                cpoint_.wait(std::chrono::seconds(1));
            }
        } catch (const cancelled_error&) {
            std::cout << "thread cancelled\n";
        }
    }
    std::unique_ptr<std::thread> thread_;
    cancellation_point cpoint_;
};

int main() {
    ThreadExample ex;
    ex.start();
    ex.stop();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*x F 2

我同意这个决定。例如,.NET 允许中止任何工作线程,我从不使用此功能,也不建议任何专业程序员这样做。我想自己决定,工作线程何时可能被中断,以及如何做到这一点。对于硬件、I/O、UI 和其他线程来说是不同的。如果线程可能在任何地方停止,这可能会导致资源管理、事务等方面的未定义程序行为。