I think the source code below may not end forever.
Assume that all waiter threads have entered the wait state. After that, waker call notify_all()
One thread, t1, wakes up and does something. And Other threads wake up while working, but mutex is occupied by t1, so it returns to the wait state.
That other thread falls asleep forever, so this program doesn't end.
#include <chrono>
#include <condition_variable>
#include <mutex>
#include <thread>
#include <vector>
using namespace std;
mutex m;
condition_variable cv;
bool isStop = false;
void waiter()
{
unique_lock<mutex> ul(m);
cv.wait(ul, []() { return isStop; });
// ...do something...
}
void waker()
{
this_thread::sleep_for(chrono::seconds(1));
unique_lock<mutex> ul(m);
isStop = true;
ul.unlock();
cv.notify_all();
}
void main()
{
vector<thread> ts;
for (int i = 0; i < 100; ++i)
ts.emplace_back(waiter);
thread w(waker);
for (auto& t : ts)
t.join();
w.join();
}
so I think that waiter function need to Unlock and notify
void waiter()
{
unique_lock<mutex> ul(m);
cv.wait(ul, []() { return isStop; });
// ...do something...
ul.unlock();
cv.notify_all();
}
Do you think I'm right?
waiterthread to wake up. Eventually, that first thread will release the mutex, and then some other thread will acquire it. And so they will go and "do something", one by one. Those threads are no longer waiting on the condition variable, so there's no point callingnotify_allagain.wakerstarts first, runs to completion, and terminates before any waiters get to start, the program is still correct. That'd mean that, by the timewaiterchecksisStopfor the first time, it's alreadytrueand so the thread never blocks on the condition variable and proceeds straight to "do something".