while loop for condition_variable

Viewed 1864

In the following example, I don't understand the purpose of ready. What is difference with or without using ready in this example?

#include <iostream>           // std::cout
#include <thread>             // std::thread
#include <mutex>              // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void print_id (int id) {
  std::unique_lock<std::mutex> lck(mtx);
  while (!ready) cv.wait(lck);
  // ...
  std::cout << "thread " << id << '\n';
}

void go() {
  std::unique_lock<std::mutex> lck(mtx);
  ready = true;
  cv.notify_all();
}

int main ()
{
  std::thread threads[10];
  // spawn 10 threads:
  for (int i=0; i<10; ++i)
    threads[i] = std::thread(print_id,i);

  std::cout << "10 threads ready to race...\n";
  go();                       // go!

  for (auto& th : threads) th.join();

  return 0;
}
2 Answers

The reason is that cv.wait(lck); can return before the notify_all call has been made, due to things called "spurious wakeups". You can see Spurious wakeups explanation sounds like a bug that just isn't worth fixing, is that right? for some more information about the reasons for this.

Thus, the waiting/notifying threads use an additional predicate (ready in this case) to signal whether the condition was signaled or whether the condition awoke due to a spurious wakeup.

When it is not ready(ready is false) you will block thread/threads until you will call one/all of them and let them do their job. However when ready is true, you will not block any threads. It is important, because without ready flag you might block thread which should be executing and therefore there will be no information to let it run again(when you block thread you have to notify it, otherwise it will wait forever)

Related