Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional variable is stuck on waiting

Why the condition variable is stuck on waiting if it was notified in worker_thread? What am I missing here?

#include <thread>
#include <mutex>
#include <condition_variable>
#include <iostream>

std::mutex m;
std::condition_variable cv;

void worker_thread()
{
    cv.notify_one();
}

int main()
{
    std::thread worker(worker_thread);

    std::cout << "Start waiting..." << std::endl;
    std::unique_lock<std::mutex> lk(m);
    cv.wait(lk);
    std::cout << "Finished waiting..." << std::endl;

    worker.join();

    getchar();
}
like image 385
theateist Avatar asked Oct 17 '25 22:10

theateist


1 Answers

Your problem is that cv.notify_one() only wakes threads that are currently waiting. cv doesn't remember you notified it, and someone later comes along and waits.

Your worker thread is outpacing your main thread. So the notify happens before the main thread.

This is just a symptom of your real problem; you are using a condition variable wrong. Barring extremely advanced use, all use of condition variable should be in a triple.

  1. A std::condition_variable.

  2. A std::mutex.

  3. A payload.

Your code is missing the payload.

To signal, you:

std::unique_lock<std::mutex> l(m);
payload = /* move it to a 'set' or 'non-empty' state */;
cv.notify_one(); // or all

to listen you:

std::unique_lock<std::mutex> l(m);
cv.wait(l, [&]{ return /* payload is in a set or non-empty state */; });
// while locked, consume one "unit" of payload from the payload.

with minor variations for wait_for and the like.

Following this cargo-cult pattern is important, as it avoids a number of pitfalls. It deals with both spurious wakeups with the wait happening after the notification.

Your code is missing a payload. So your code is vulnerable to both the waiting thread outrunning the signaling thread, and spurious wakeups.

Note that getting "clever" here is highly discouraged. For example, deciding that "I'll use an atomic variable to avoid using a mutex when signaling" actually doesn't work. Either follow the above recipe dogmatically, or go and spend a few months learning the threading and memory model of C++ well enough to improvise.

like image 143
Yakk - Adam Nevraumont Avatar answered Oct 19 '25 13:10

Yakk - Adam Nevraumont



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!