condition_variable并不总是有效

时间:2016-02-27 13:50:01

标签: c++ multithreading concurrency parallel-processing

似乎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();
    }
}

这个程序几乎永远不会到达终点,绝大部分时间都会在循环中永久停止。 为什么会这样?

2 个答案:

答案 0 :(得分:4)

这里有两个错误:

  • 如果同步对象的访问权限,则不需要该对象的原子类型。你的atomic_bool只会造成开销。
  • 如果要同步对launch标志的访问,则需要在写入之前锁定其互斥锁。您不是在main()
  • 中执行此操作

说明:

  1. main()创建task
  2. main()创建thread
  3. job()锁定互斥锁
  4. job()检查launch,这是假的
  5. main()设置launch
  6. main()发出无人接收的简历
  7. job()由于第4步中launch的值而等待简历
  8. 通常,步骤3和6将是原子的,因为任何其他线程都不应该在不锁定互斥锁的情况下触及launch。由于没有发生这种情况,允许进行相关操作的交错,最终导致意外行为。

答案 1 :(得分:1)

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