【问题标题】:Using a single Condition Variable to pause multiple threads使用单个条件变量暂停多个线程
【发布时间】:2018-11-13 00:01:09
【问题描述】:

我有一个启动 N 个线程(异步/未来)的程序。我想让主线程设置一些数据,然后所有线程都应该去,而主线程等待所有其他线程完成,然后这需要循环。

我的atm是这样的

int main()
{  
    //Start N new threads (std::future/std::async)
    while(condition)
    {
       //Set Up Data Here
       //Send Data to threads
       {
           std::lock_guard<std::mutex> lock(mrun);
           bRun = true;

       }
       run.notify_all();
       //Wait for threads
       {
           std::unique_lock<std::mutex> lock(mrun);
           run.wait(lock, [] {return bDone; });
       }
       //Reset bools
       bRun = false;
       bDone = false;
    }
    //Get results from futures once complete
}

int thread()
{
    while(otherCondition)
    {
       std::unique_lock<std::mutex> lock(mrun);
       run.wait(lock, [] {return bRun; });
       bDone = true;
       //Do thread stuff here
       lock.unlock();
       run.notify_all();
    }
}

但是我看不到任何主线程或其他线程在等待对方的迹象!知道我做错了什么或者我该怎么做吗?

【问题讨论】:

    标签: c++ multithreading asynchronous condition-variable


    【解决方案1】:

    有几个问题。首先,您将在第一个工作人员醒来时设置bDone。因此主线程立即唤醒并开始准备下一个数据集。您想让主线程等待,直到所有工作人员完成处理他们的数据。其次,当工作人员完成处理时,它会循环并立即检查bRun。但它无法判断bRun == true 是否意味着下一个数据集已准备就绪,或者 last 数据集是否已准备好。您想等待下一个数据集。

    这样的事情应该可以工作:

    std::mutex mrun;
    std::condition_variable dataReady;
    std::condition_variable workComplete;
    
    int nCurrentIteration = 0;
    int nWorkerCount = 0;
    
    int main()
    {
      //Start N new threads (std::future/std::async)
      while(condition)
      {
        //Set Up Data Here
        //Send Data to threads
        {
           std::lock_guard<std::mutex> lock(mrun);
           nWorkerCount = N;
           ++nCurrentIteration;
        }
        dataReady.notify_all();
        //Wait for threads
        {
           std::unique_lock<std::mutex> lock(mrun);
           workComplete.wait(lock, [] { return nWorkerCount == 0; });
        }
      }
      //Get results from futures once complete
    }
    
    int thread()
    {
      int nNextIteration == 1;
    
      while(otherCondition)
      {
        std::unique_lock<std::mutex> lock(mrun);
        dataReady.wait(lock, [&nNextIteration] { return nCurrentIteration==nNextIteration; });
        lock.unlock();
    
        ++nNextIteration;
    
        //Do thread stuff here
    
        lock.lock();
        if (--nWorkerCount == 0)
        {
          lock.unlock();
          workComplete.notify_one();
        }
      }
    }
    

    请注意,此解决方案并不完整。如果一个worker遇到异常,那么主线程就会挂起(因为死掉的worker永远不会减少nWorkerCount)。您可能需要一种策略来处理这种情况。

    顺便说一下,这种模式称为barrier

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-13
      • 2018-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-25
      • 1970-01-01
      相关资源
      最近更新 更多