简体   繁体   English

使用单个条件变量暂停多个线程

[英]Using a single Condition Variable to pause multiple threads

I have a program that starts N number of threads (async/future). 我有一个启动N个线程的程序(异步/未来)。 I want the main thread to set up some data, then all threads should go while the main thread waits for all of the other threads to finish, and then this needs to loop. 我希望主线程设置一些数据,然后所有线程应该在主线程等待所有其他线程完成时进行,然后这需要循环。

What I have atm is something like this 我的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();
    }
}

But I can't see any signs of either the main or the other threads waiting for each other! 但我看不出任何主线或其他线程互相等待的迹象! Any idea what I am doing wrong or how I can do this? 知道我做错了什么或我怎么做到这一点?

There are a couple of problems. 有几个问题。 First, you're setting bDone as soon as the first worker wakes up. 首先,一旦第一个工人醒来,你就会设置bDone Thus the main thread wakes immediately and begins readying the next data set. 因此,主线程立即唤醒并开始准备下一个数据集。 You want to have the main thread wait until all workers have finished processing their data. 您希望主线程等到所有工作人员完成数据处理。 Second, when a worker finishes processing, it loops around and immediately checks bRun . 其次,当一个工人完成处理时,它会循环并立即检查bRun But it can't tell if bRun == true means that the next data set is ready or if the last data set is ready. 但它无法判断bRun == true表示下一个数据集是否准备就绪或者最后一个数据集是否准备就绪。 You want to wait for the next data set. 您想等待下一个数据集。

Something like this should work: 这样的事情应该有效:

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

Be aware that this solution isn't quite complete. 请注意,此解决方案并不完整。 If a worker encounters an exception, then the main thread will hang (because the dead worker will never reduce nWorkerCount ). 如果一个worker遇到异常,那么主线程将挂起(因为死工人永远不会减少nWorkerCount )。 You'll likely need a strategy to deal with that scenario. 您可能需要一种策略来处理该场景。

Incidentally, this pattern is called a barrier . 顺便提一下,这种模式称为barrier

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM