【问题标题】:Interupt boost thread that is already in condition variable wait call中断已经处于条件变量等待调用中的 boost 线程
【发布时间】:2015-04-12 23:21:41
【问题描述】:

我正在使用boost interprocess library 创建服务器和客户端程序,以便在共享内存中传递opencv mat objects。每个服务器和客户端进程都有两个 boost 线程,它们是 boost::thread_group 的成员。一个处理命令行 IO,而另一个管理数据处理。共享内存访问使用 boost::interprocess condition_variables 同步。

由于这个程序涉及共享内存,我需要在退出前进行一些手动清理。我的问题是,如果服务器过早终止,则客户端上的处理线程会在 wait() 调用处阻塞,因为服务器负责发送通知。我需要以某种方式中断卡在wait() 的线程以启动共享内存销毁。我了解在线程上调用interrupt()(在我的情况下为thread_group.interrupt_all())将导致在到达中断点(例如wait())时抛出boost::thread_interrupted 异常,这如果不处理,将允许共享内存破坏继续进行。但是,当我尝试在wait() 中中断线程时,似乎什么也没有发生。例如,这不会在命令行中打印任何内容:

try {
    shared_mat_header->new_data_condition.wait(lock);
} catch (...) {
    std::cout << "Thread interrupt occurred\n";
}

我完全不确定,但似乎interrupt() 调用需要在线程进入wait() 之前发生才能引发异常。这是真的?如果不是,那么中断被 condition_variable.wait() 调用阻塞的 boost 线程的正确方法是什么?

感谢您的任何见解。

编辑 我接受了 Chris Desjardins 的回答,它没有直接回答问题,但具有预期的效果。在这里,我将他的代码 sn-p 翻译为与boost::interprocess 条件变量一起使用,其语法与boost::thread 条件变量略有不同:

while (_running) {

    boost::system_time timeout = boost::get_system_time() + boost::posix_time::milliseconds(1);

    if (shared_mat_header->new_data_condition.timed_wait(lock, timeout)) 
    {
        //process data
    }
}

【问题讨论】:

    标签: c++ multithreading opencv boost


    【解决方案1】:

    我更喜欢等待超时,然后检查等待调用的返回码,看看它是否超时。事实上,我有一个我喜欢使用的线程模式来解决这种情况(以及 c++ 中线程的其他常见问题)。

    http://blog.chrisd.info/how-to-run-threads/

    你的要点是不要在一个线程中无限阻塞,所以你的线程看起来像这样:

    while (_running == true)
    {
        if (shared_mat_header->new_data_condition.wait_for(lock, boost::chrono::milliseconds(1)) == boost::cv_status::no_timeout)
        {
            // process data
        }
    }
    

    然后在你的析构函数中设置 _running = false;并加入线程。

    【讨论】:

    • 谢谢你,克里斯。我可以接受的这个变体已添加到我原始问题的编辑中。我仍然有点困惑,因为切换到timed_wait 调用,我尝试使用thread_group.interrupt_all() 调用来查看是否因为timed_wait 每毫秒自动输入和退出,我可以获得boost::thread_interrupted要抛出的异常。但是,仍然没有任何反应。如果您对中断不起作用的原因有任何想法,那就太好了。
    • 嗯 - 我想我明白了。我正在使用boost::interprocess 条件变量。引用here 的中断点可能仅适用于boost::condition_variable 而不是boost::interprocess::condition_variable
    • 我的想法是,正如您所说:当您所做的只是多线程时,不要使用进程间通信结构。
    【解决方案2】:

    尝试使用“通知功能”。保留一个指向您的条件变量的指针并调用它而不是中断线程。中断比通知调用代价更高。

    所以不要这样做

    thread_group.interrupt_all()
    

    改为调用它

    new_data_condition_pointer->notify_one()
    

    【讨论】:

    • 我不确定我是否完全理解。至少现在,只有服务器通知客户端。由于服务器进程已经终止,它不能再发出通知调用来让客户端离开wait()。客户端线程卡在wait(),因此无法发出notify_one() 调用。我想这个想法是将new_data_condition_pointer保留在第二个IO线程上,并在服务器故障后使用它来发出通知?
    猜你喜欢
    • 1970-01-01
    • 2013-05-30
    • 1970-01-01
    • 2011-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多