即使调用notify_all,工作线程也始终在condition_variable中等待

时间:2019-12-10 12:27:30

标签: c++ multithreading

我得到如下代码:

std::mutex mutex;
std::condition_variable condition_variable;
bool finish = false;

void test() {
  while (true) {
    std::unique_lock<std::mutex> lock(mutex);
    condition_variable.wait(lock);
    if (finish){
      std::cout << "finish detected" << std::endl;
      return;
    }
  }
}

int main() {
  std::thread t(test);
  std::unique_lock<std::mutex> lock(mutex);
  finish = true;
  lock.unlock();
  //sleep(1);
  condition_variable.notify_all();
  std::cout << "notify_all" << std::endl;
  t.join();
}

并且代码在运行时不会终止,将显示notify_all日志,但不会显示finish detected日志。如果使用调试模式,则代码将成功终止,因此无法提供有关正在运行的代码状态的清晰线索,但是如果释放sleep(1),则代码将起作用。

那么任何人都可以帮助解决我的代码有什么问题吗?

1 个答案:

答案 0 :(得分:5)

条件变量没有状态,因此当您发出信号且没有服务员时,信号会丢失。当condition_variable.notify_all()condition_variable.wait(lock);之前执行时,它会在您的代码中发生。

代码没有使用正确的方法来等待条件变量。正确的方法是:

  1. 锁定互斥锁。
  2. 检查条件(此处{finish)。
  3. 如果不满足条件,请等待条件变量。 The condition variable can be woken up spuriously。转到2。

修复:

void test() {
    std::unique_lock<std::mutex> lock(mutex);
    while(!finish)
        condition_variable.wait(lock);
    std::cout << "finish detected" << std::endl;
}

condition_variable::wait的另一个重载会为您执行while循环:

void test() {
    std::unique_lock<std::mutex> lock(mutex);
    condition_variable.wait(lock, [&finish]{ return finish; });
    std::cout << "finish detected" << std::endl;
}