Do I need to lock the mutex before calling condition_variable::notify()?
Asked Answered
B

1

6

I'm reading some example code of condition_variable:

At cppreference, the notify_one() is called like this: https://en.cppreference.com/w/cpp/thread/condition_variable

{
    std::lock_guard lk(m);
    ready = true;
    std::cout << "main() signals data ready for processing\n";
}
cv.notify_one();

from the code above, it's clear that it's not necessary to use any mutex to call notify_one().

But at cplusplus.com, the code is like this: https://cplusplus.com/reference/condition_variable/condition_variable/

std::unique_lock<std::mutex> lck(mtx);
ready = true;
cv.notify_all();

It seems that a mutex should be used before calling notify_all().

I'm confused, is a mutex necessary for notify_*() function?

Breann answered 30/8, 2022 at 13:55 Comment(4)
the mutex is locked to synchronize ready = true in both examplesFestal
cppreference specifically says "the lock does not need to be held for notification". You only need the lock to modify the shared variable, though you need the lock even if the shared variable is atomic.Coven
A side note: IMHO cppreference.com is a better source than cplusplus.com.Deanadeanda
You require the 'lock' only for the 'wait', if I recall correctly.Apocarp
D
3

It is not mandatory to call notify_one or notify_all under the lock holding the mutex.

From the std::condition_variable documentation:
The 3rd thing the thread that intends to modify the shared variable has to do is:

execute notify_one or notify_all on the std::condition_variable (the lock does not need to be held for notification)

(emphasis is mine).

However - it might offer some performance benefit to call notify_* under the lock.

From the comment to my answer here (credit goes to @DavidSchwartz):

You gratuitously make the notify_all more expensive by unlocking the mutex before calling it. If you call notify_all while holding the mutex, most modern implementations know that it cannot make any thread ready-to-run (because they need to acquire the mutex to make forward progress) and can make wait morphing optimizations. The way this is coded, both notify_all and the destructor of lck can make a thread ready-to-run, resulting in reduced performance.

Deanadeanda answered 30/8, 2022 at 14:12 Comment(3)
Very interesting input, thanks. I always assumed the opposite, as the doc still states that "The notifying thread does not need to hold the lock on the same mutex as the one held by the waiting thread(s); in fact doing so is a pessimization, since the notified thread would immediately block again, waiting for the notifying thread to release the lock." Sounds like smart modern compilers require a change in my coding :)Terti
@Terti at en.cppreference.com/w/cpp/thread/condition_variable/notify_one it mentions the pthreads approach, tooKoffman
If my answer solved your issue @FelixFXu you can consider to accept it by by clicking the check mark ('✔'). See: What should I do when someone answers my question?.Deanadeanda

© 2022 - 2024 — McMap. All rights reserved.