【问题标题】:boost condition. What am I doing wrong?升压条件。我究竟做错了什么?
【发布时间】:2011-04-16 22:50:34
【问题描述】:
boost::condition_variable cond;
boost::mutex mut;

void Database::run()
{
    boost::unique_lock<boost::mutex> lock(mut);

    while(true)
    {
        while(queries_queue.empty())
            cond.wait(lock);

        mysqlpp::Query* q = queries_queue.front(); // <<< CRASHES HERE <<<
        q->execute();
        queries_queue.pop_front();
    }
}

void Database::Execute(mysqlpp::Query* q)
{
    {
        boost::lock_guard<boost::mutex> lock(mut);
        queries_queue.push_back(q);
    }
    cond.notify_one();
}

run 由 boost::thread 执行。 Execute 由主程序线程调用以对操作进行排队。 但是,它在从条件等待唤醒后崩溃。

我做错了什么?

【问题讨论】:

  • 顺便说一句,你应该给你的条件变量一个更具描述性的名字
  • btw2,在执行函数 q->execute() 时,互斥锁仍然被锁定是故意的吗?
  • 我看不出有什么问题。错误可能在其他地方。
  • 我不太了解 Boost.Threads,但您在一个函数中使用 lock_guard 而在另一个函数中使用 unique_lock 是否正常?
  • @wilx:lock_guard/unique_lock 的选择是合适的。

标签: c++ boost conditional-statements boost-thread


【解决方案1】:

您的线程代码看起来不错。唯一有气味的是混合lock_guardunique_lock 但这没什么大不了的。但是,我有 99% 的把握,你的代码不是在你所说的地方崩溃,而是在下一行 - q-&gt;execute();Database::Execute () 方法的调用者似乎正在传递一个指向在堆栈上分配的查询对象的指针,或者,如果它是动态分配的,它会在函数完成后立即将其删除。但是,稍后,您的线程会重试指向该已删除(释放或破坏)对象的指针并尝试执行它。另一种可能性是 NULL 指针被传递给 Database::Execute () 导致相同的结果。

【讨论】:

  • lock_guard 很好,如果他不必将锁对象传递给条件变量。
  • 尝试评论 q->执行并删除 q。坠机持续。但是当我删除了对 queries_queue 的两个引用时,它起作用了。
  • @Vladimir:是否有其他东西可以访问queries_queue 可能没有锁定?另外,在您的示例中,我没有看到任何 delete q;。如果您可以提供一个崩溃的最小工作代码示例,那将有很大帮助。否则它总是在猜测。但问题绝对不在你目前提供的线程代码上。
【解决方案2】:

试试

while(true)
{
    boost::unique_lock<boost::mutex> lock(mut);
    while(queries_queue.empty())
        cond.wait(lock);

【讨论】:

  • 重新锁定mutex 毫无意义。这就是 condition::wait 的意义所在。
  • @Vlad:我认为 aaa 意味着将boost::unique_lock&lt;boost::mutex&gt; lock(mut); 从函数范围移动到Database::run 中的while(true) 范围,而不是添加另一个。
  • @Eugen:没错,这将在while 循环的每次交互中引入锁定/解锁。这是非常有害的。
猜你喜欢
  • 2013-08-06
  • 1970-01-01
  • 2016-07-18
  • 2019-12-23
  • 2014-06-15
  • 1970-01-01
  • 2015-08-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多