Reputation: 14399
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();
}
Upvotes: 4
Views: 3636
Reputation: 275385
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.
A std::condition_variable
.
A std::mutex
.
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.
Upvotes: 2
Reputation: 32732
notify_one
will unblock a waiting thread if there is one. If there are no waiting threads, nothing happens. A condition_variable
does not have a state to remember how many threads should be notified when it is waited on.
Upvotes: 1