我的代码中存在与条件变量的使用相关的死锁问题。这更多的是设计问题,而不是纯粹的代码问题。了解正确的设计后,我便可以真正编写代码了。我有以下情况:

  • 线程A等待条件变量。
  • 线程B调用notify_all,线程A醒来。

  • 这当然是我想发生的事情,并且当一切都按预期工作时会发生什么。但有时,我得到以下情形:
  • 线程A在开始等待条件变量之前立即执行代码。
  • 线程B调用notify_all,认为线程A正在等待。
  • 线程A开始等待条件变量,但没有意识到线程B已经告诉它停止等待。僵局。

  • 解决此问题的最佳方法是什么?我想不出一种可靠的方法来检查线程A是否实际上正在等待,以便知道何时应在线程B中调用notify_all。我是否必须求助于timed_lock?我讨厌

    最佳答案

    在线程A等待条件变量之前的一段时间内,它必须持有互斥量。最简单的解决方案是确保线程B在调用notify_all时保持相同的互斥量。所以像这样:

    std::mutex m;
    std::condition_variable cv;
    int the_condition = 0;
    
    Thread A: {
      std::unique_lock<std::mutex> lock(m);
      do something
      while (the_condition == 0) {
        cv.wait(lock);
      }
      now the_condition != 0 and thread A has the mutex
      do something else
    } // releases the mutex;
    
    Thread B: {
      std::unique_lock<std::mutex> lock(m);
      do something that makes the_condition != 0
      cv.notify_all();
    } // releases the mutex
    

    这保证了线程B仅在线程A获取互斥量之前或在线程A等待条件变量时才执行notify_all()。

    但是,这里的另一个关键是while循环,等待the_condition变为true。一旦A具有互斥量,则在A测试了_condition,发现它为false并开始等待(从而释放互斥量)之前,其他任何线程都不可能更改_condition。

    关键是:您真正在等待的是the_condition的值变为非零,std::condition_variable::notify_all只是告诉您线程B认为线程A应该唤醒并重新测试。

    10-08 01:23