【问题标题】:condition_variable not always working条件变量并不总是有效
【发布时间】:2016-02-27 13:50:01
【问题描述】:

似乎condition_variable notify_one 并不总是按应有的方式工作。

struct Task {
    std::mutex mutex;
    std::condition_variable cv;
    std::atomic_bool launch{false};
};
void job(Task& task) {
    std::unique_lock<std::mutex> lock{task.mutex};
    task.cv.wait(lock, [&]{ return task.launch == true; });
}
int main() {
    for (auto i=0 ; i<1000*1000 ; i++) {
        Task task;
        std::thread thread{job, std::ref(task)};
        task.launch = true;
        task.cv.notify_one();
        thread.join();
    }
}

这个程序几乎永远不会到达终点,它在绝大多数情况下都永远停止在循环中。 为什么会这样?

【问题讨论】:

  • 会发生什么,您预计会发生什么?这些是一个好问题的基本部分......
  • 谢谢@UlrichEckhardt,我希望程序能够完成,但它几乎永远不会完成。
  • 它到底挂在哪里?哪一行是最后成功执行的?

标签: c++ multithreading concurrency parallel-processing


【解决方案1】:

这里有两个错误:

  • 如果您同步访问某个对象,则不需要该对象的原子类型。您的 atomic_bool 只会造成开销。
  • 如果您想同步访问launch 标志,您需要在写入之前锁定它的互斥锁。你不会在main() 中这样做。

解释:

  1. main() 创建 task
  2. main() 创建 thread
  3. job() 锁定互斥体
  4. job() 检查launch,这是错误的
  5. main() 设置launch
  6. main() 发送简历,没人收到
  7. 由于步骤 4 中 launch 的值,job() 等待 CV

通常,第 3 步和第 6 步将是原子的,因为在没有锁定互斥锁的情况下,任何其他线程都不应该接触launch。由于没有发生这种情况,因此允许发生依赖操作的交错,这最终导致了意外行为。

【讨论】:

  • 所以具体来说,job() 在第 6 步等待 CV 的 原因 是因为 main 函数没有将写入同步到 launch 和所以线程不一定能看到变化?如果线程认为launch 为真,那么它永远不会阻塞条件变量,因为condition_variable::wait 在等待之前会检查谓词。
  • 想一想,也许我的解释是错误的,@SteveJessop。此外,你的也没有改进它,因为atomic&lt;bool&gt; 应该让它变得安全。我将添加另一个解释。
  • 这就是我一直在努力解决的问题。我现在认为我的问题的答案是“不”。 atomic 类型意味着 CV 上的阻塞按照main 写入launch 的顺序排列。但是在main 通知 CV 之后,仍然没有任何东西可以对 CV 上的线程阻塞进行排序。
  • 为什么在第 6 步期间没有人收到?是的,job()4) 期间检查过,但它仍在这个条件变量中等待
  • 等待带有谓词回调 (lambda) 的 CV 首先检查谓词(步骤 4)。然后,它以原子方式解锁 CV 上的互斥锁和块(步骤 7)。在第 4 步之后它不会被阻止。这是有效的,因为条件受互斥锁保护,除非有人(在本例中为 main())违反合同并在没有持有互斥锁的情况下访问数据。
【解决方案2】:

不清楚你想要什么,但你的问题是主线程可能在线程有时间调用wait之前实现launch=truenotify_one()。在这种情况下,您应该知道notify 没有延迟,因此您的主线程将在join 上被阻塞,而线程在wait 上被阻塞。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-17
    • 2012-12-26
    • 1970-01-01
    • 1970-01-01
    • 2012-04-23
    • 2015-06-28
    • 2015-12-04
    • 2017-01-08
    相关资源
    最近更新 更多