Search code examples
c++multithreadingc++11condition-variable

std::condition_variable wait() and notify_one() synchronization


Preface: I've seen similar questions here, but not one of them seems to answer my question.

Is there a reliable way to make sure that wait() method in consumer thread is called before the first notify_one() call from the producer thread?

Even with unique_lock in the consumer thread, there is a possibility that the producer thread will run first, lock the mutex and call notify() before the consumer calls wait(), therefore, my app will be missing first notify() call.

EDIT: Thanks for all your answers, they did help me. My problem was with first wait-notify() within this consumer loop:

while (!timeToQuit) {
    gdcv.wait(gdcondlock);
    gdlock.lock();
    //spurious wakeup
    if (gdQueue.empty()) {
      gdlock.unlock();
      continue;
    }
    //some work here
    gdlock.unlock();
} 

I guess I'll have to write extra code for the first loop iteration.

EDIT2: This loop and second lock(unique_lock btw) are there because there are multiple producers and consumers accessing queue.

EDIT3: The correct way for waiting on this particular thread with the help of boost::lockfree::queue, in case anyone has similar problem:

  nfq_data* data;
  while (!timeToQuit) {
    gdcv.wait(gdlock,[&]{return !gdQueue.empty() || timeToQuit;});
    gdQueue.pop(data);
    gdlock.unlock();
  }

Solution

  • Even with unique_lock in consumer thread there is a possibility that producer thread will run first, lock the mutex and call noify() before consumer calls wait(), therefore, my app will be missing first nofity() call.

    Either the consumer has something to wait for, or it doesn't. If it has something to wait for, there is no problem. If it doesn't have anything to wait for, don't call wait. It really is that simple.

    Call wait if, and only if, you want to wait.

    Condition variables exist to solve the problem of how you can release a lock and wait without taking the risk that you will wait for something that has already happened. They solve it by providing a function that atomically releases the lock and waits. They cannot miss a wakeup because they hold the lock when they decide to sleep.