首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >条件变量不起作用,但是在添加std::cout之后,它正在工作。

条件变量不起作用,但是在添加std::cout之后,它正在工作。
EN

Stack Overflow用户
提问于 2015-06-15 07:40:33
回答 2查看 528关注 0票数 0

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

代码语言:javascript
复制
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;
  }

}

绘制函数只是向另一个线程发出信号,表示接收到了一个新任务。

代码语言:javascript
复制
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();

}

其他线程的主体如下。它等待任务到达,然后开始处理:

代码语言:javascript
复制
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;运行另一个线程,但是如果我在SubApplication::draw()的开头添加了一个std::cout << "Draw\n";,它就会正常工作。我正在寻找它发生的原因,以及修复它的通常方法是什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-06-15 09:28:16

代码语言:javascript
复制
boost::lock_guard<boost::mutex> lock(task_received_mutex);
task_received = true;

好,task_received_mutex保护task_received

代码语言:javascript
复制
    boost::unique_lock<boost::mutex> start_lock(task_start_mutex);
    while (!task_received){
      task_start_condition.wait(start_lock);
    }

哎呀,我们在读task_received时没有拿着保护它的互斥物。是什么阻止一个线程读取task_received,而另一个线程正在修改它呢?这可能立即导致僵局。

此外,您的代码声称“等待直到所有子应用程序完成绘图”,但没有调用任何等待函数。因此,它实际上是旋转而不是等待,这是可怕的。

票数 1
EN

Stack Overflow用户

发布于 2015-06-15 09:23:15

首先,在task_start_condition锁下向task_start_mutex发送信号。

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

第三:您似乎有几个以“逻辑任务”命名的互斥对象(绘制、开始)。然而,在现实中,互斥保护资源,而不是“逻辑任务”。因此,用他们应该保护的共享资源来命名他们是很好的做法。_(在这种情况下,我得到的印象是一个互斥可以足够/更好)。但我们不能从所示的代码中确定))。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30839734

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档