条件变量不起作用,但在添加 std::cout 后,它起作用了

The conditional variable is not working but after adding std::cout, it is working

我的项目由两个线程组成:一个主线程和另一个处理另一个 window 内容的线程。因此,当主线程想要请求另一个 windows 更新自身时,它会调用绘制函数,如下所示:

void SubApplicationManager::draw() {

  // Zero number of applications which has finished the draw counter
  {
    boost::lock_guard<boost::mutex> lock(SubApplication::draw_mutex);
    SubApplication::num_draws = 0;
  }

  // Draw the sub applications.
  for (size_t i = 0; i < m_subApplications.size(); i++)
    m_subApplications[i].signal_draw();

  // Wait until all the sub applications finish drawing.
  while (true){
    boost::lock_guard<boost::mutex> lock(SubApplication::draw_mutex);
    std::cout << SubApplication::num_draws << std::endl;
    if (SubApplication::num_draws >= m_subApplications.size()) break;
  }

}

draw 函数只是向另一个线程发出信号,表明已收到新任务。

void SubApplication::signal_draw() {

  task = TASK::TASK_DRAW;
  {
    boost::lock_guard<boost::mutex> lock(task_received_mutex);
    task_received = true;
  }
  task_start_condition.notify_all();

}

其他线程正文如下。它等待任务到达然后开始处理:

void SubApplication::thread() {

  clock_t start_time, last_update;
  start_time = last_update = clock();

  //! Creates the Sub Application
  init();

  while (!done)                                                       // Loop That Runs While done=FALSE
  {
      // Draw The Scene.  Watch For ESC Key And Quit Messages From DrawGLScene()
      if (active)                                       // Program Active?
      {
        // Wait here, until a update/draw command is received.
        boost::unique_lock<boost::mutex> start_lock(task_start_mutex);
        while (!task_received){
          task_start_condition.wait(start_lock);
        }

        // Task received is set to false, for next loop.
        {
          boost::lock_guard<boost::mutex> lock(task_received_mutex);
          task_received = false;
        }

        clock_t frame_start_time = clock();

        switch (task){
        case TASK_UPDATE:
          update();
          break;

        case TASK_DRAW:
          draw();
          swapBuffers();
          break;

        case TASK_CREATE:
          create();
          break;

        default:
          break;
        }

        clock_t frame_end_time = clock();
        double task_time = static_cast<float>(frame_end_time - frame_start_time) / CLOCKS_PER_SEC;

      }
  }
}

问题是,如果我按原样 运行 代码,它永远不会 运行 另一个线程 task = TASK::TASK_DRAW; 但是如果我添加 std::cout << "Draw\n"; SubApplication::draw() 的开头,它将正常工作。我正在寻找它发生的原因以及通常的修复方法是什么?

作为初学者,在 task_start_mutex 锁下发出 task_start_condition 信号。

考虑在线程创建期间锁定该互斥锁以避免明显的竞争。

第三:您似乎有几个以 "logical tasks" 命名的互斥量(绘制,开始)。然而,实际上,互斥体保护资源,而不是 "logical tasks"。因此,最好以它们应该保护的共享资源来命名它们。 _(在这种情况下,我的印象是单个互斥体可能是 enough/better。但我们无法从显示的代码中确定))。

boost::lock_guard<boost::mutex> lock(task_received_mutex);
task_received = true;

好的,task_received_mutex 保护 task_received

    boost::unique_lock<boost::mutex> start_lock(task_start_mutex);
    while (!task_received){
      task_start_condition.wait(start_lock);
    }

哎呀,我们正在读取 task_received,但没有持有保护它的互斥量。是什么阻止了一个线程读取 task_received 而另一个线程正在修改它的竞争?这可能会立即导致死锁。

此外,您的代码声称 "Wait until all the sub applications finish drawing" 但没有调用任何等待函数。所以它实际上是旋转而不是等待,这太糟糕了。