C++11 std::condition_variable - notify_one() 未按预期运行?

C++11 std::condition_variable - notify_one() not behaving as expected?

我看不出这个程序有任何实际用途,但在试验 c++ 11 并发性和 conditional_variables 时,我偶然发现了一些我不完全理解的东西。

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

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

If any threads are waiting on *this, calling notify_one unblocks one of the waiting threads.

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

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);
      }
    }
  }
};

提供的代码 "works" 正确并被设计卡住。 documentation

中描述了原因

The effects of notify_one()/notify_all() and wait()/wait_for()/wait_until() take place in a single total order, so it's impossible for notify_one() to, for example, be delayed and unblock a thread that started waiting just after the call to notify_one() was made.

一步一步的逻辑是

  1. print_odd_natural_numbers线程已启动
  2. print_even_natural_numbers 线程也已启动。
  3. print_even_natural_numbersm_condition.notify_all(); 行在 print_odd_natural_numbers 线程到达 m_condition.wait(lock); 行之前执行。
  4. 执行了print_odd_natural_numbersm_condition.wait(lock);行,线程卡住了。
  5. print_even_natural_numbersm_condition.wait(lock); 行被执行,线程也被卡住了。