C ++ 11 std :: condition_variable - notify_one()表现不如预期?

时间:2015-05-09 03:39:51

标签: c++11 concurrency conditional

我没有看到这个程序有任何实际用法,但在尝试使用c ++ 11并发和conditional_variables时,我偶然发现了一些我并不完全理解的内容。

起初我假设使用notify_one()将允许下面的程序工作。然而,实际上程序在打印之后就冻结了。当我切换到使用notify_all()时,程序完成了我想要它做的事情(按顺序打印所有自然数字)。我相信这个问题已经以各种形式提出。但我的具体问题是我在doc读错的地方。

我认为notify_one()应该有效,因为以下陈述。

  

如果有任何线程正在等待* this,则调用notify_one将解锁其中一个等待线程。

在下面看,只有一个线程会在给定时间被阻止,对吗?

class natural_number_printer
{
public:
  void run()
  {
    m_odd_thread = std::thread(
      std::bind(&natural_number_printer::print_odd_natural_numbers, this));
    m_even_thread = std::thread(
      std::bind(&natural_number_printer::print_even_natural_numbers, this));

    m_odd_thread.join();
    m_even_thread.join();
  }

private:
  std::mutex m_mutex;
  std::condition_variable m_condition;

  std::thread m_even_thread;
  std::thread m_odd_thread;

private:
  void print_odd_natural_numbers()
  {
    for (unsigned int i = 1; i < 100; ++i) {
      if (i % 2 == 1) {
        std::cout << i << " ";
        m_condition.notify_all();
      } else {
        std::unique_lock<std::mutex> lock(m_mutex);
        m_condition.wait(lock);
      }
    }
  }

  void print_even_natural_numbers()
  {
    for (unsigned int i = 1; i < 100; ++i) {
      if (i % 2 == 0) {
        std::cout << i << " ";
        m_condition.notify_all();
      } else {
        std::unique_lock<std::mutex> lock(m_mutex);
        m_condition.wait(lock);
      }
    }
  }
};

1 个答案:

答案 0 :(得分:2)

提供的代码“正常”工作并被设计卡住。原因在documentation

中描述
  

notify_one()/ notify_all()和的效果   wait()/ wait_for()/ wait_until()在一个总订单中发生,所以   例如,notify_one()不可能被延迟   取消阻止在调用之后开始等待的线程   notify_one()已经完成。

分步逻辑是

  1. print_odd_natural_numbers线程已启动
  2. print_even_natural_numbers线程也已启动。
  3. m_condition.notify_all(); print_even_natural_numbers行之前执行print_odd_natural_numbers线程到m_condition.wait(lock);行。
  4. 执行m_condition.wait(lock); print_odd_natural_numbers行,线程卡住。
  5. 执行m_condition.wait(lock);的{​​{1}}行,线程也被卡住了。
相关问题