I am slightly confused in mutex, lock, and wait.
Here is my code:
void producer(std::mutex* m, std::condition_variable* cv,bool* signal) {
std::this_thread::sleep_for(std::chrono::seconds(1));
m->lock();
*signal = true;
m->unlock();
std::this_thread::sleep_for(std::chrono::seconds(3));
cv->notify_one();
printf("notify one\n");
std::this_thread::sleep_for(std::chrono::seconds(10000));
}
void consumer(std::mutex*m, std::condition_variable* cv, bool* signal, int index) {
if(index == 2) std::this_thread::sleep_for(std::chrono::seconds(2));
std::unique_lock<std::mutex> lk(*m);
cv->wait(lk, [&] { return (*signal); });
printf("consumer %d passes this point!\n", index);
std::this_thread::sleep_for(std::chrono::seconds(10000));
}
int main() {
bool signal = false;
std::mutex m;
std::condition_variable cv;
std::thread th1(producer, &m, &cv, &signal);
std::thread th2(consumer, &m, &cv, &signal, 1);
std::thread th3(consumer, &m, &cv, &signal, 2);
th1.join();
th2.join();
th3.join();
return 0;
}
std::this_thread::sleep_for is added to explain my question.
There are producer, consumer1, and consumer 2. I think that this code should work as follows:
- consumer1 meets
std::unique_lock<std::mutex> lk(*m);so it locks. - consumer1 meets
cv->wait. Because initial value ofsignalisfalse, consumer1 is blocked and the lock is released. - producer meets
m->lock();,*signal = true;,m->unlock();, andsleep_for. Therefore,signalbecomestrue. - consumer2 meets
std::unique_lock<std::mutex> lk(*m);andcv->wait(lk, [&] { return (*signal); });. Becuasesignalistrue, this thread just passes it. So,printf("consumer %d passes this point!\n", index);is executed. - producer meets
cv->notify_one();. consumer 1 is unblocked and check the condition. Becausesignalisture, consumer1 can pass this point. Therefore, consumer1 meetsprintf.
Consequently, my expected result is
consumer 2 passes this point!
notify one
consumer 1 passes this point!
However, the real result is
consumer 2 passes this point!
notify one
It seems to be that consumer1 cannot pass cv->wait(lk, [&] { return (*signal); });, even though notify_one() is called and the condition is satisfied. Is there anything wrong in my understanding?
.join()so your code is running synchronously. ie. producer completes, only then does consumer 1 complete. If you use.detach()your code will run as expected (non blocking, asynchronous) (apart from the main thread exiting so add another condition variable or put it to sleep.