8

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?

4
  • the mutex is locked to synchronize ready = true in both examples Commented Aug 30, 2022 at 13:58
  • 3
    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. Commented Aug 30, 2022 at 13:58
  • 2
    A side note: IMHO cppreference.com is a better source than cplusplus.com. Commented Aug 30, 2022 at 14:02
  • You require the 'lock' only for the 'wait', if I recall correctly. Commented Aug 30, 2022 at 14:02

1 Answer 1

4

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.

Sign up to request clarification or add additional context in comments.

3 Comments

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 :)
@Cedric at en.cppreference.com/w/cpp/thread/condition_variable/notify_one it mentions the pthreads approach, too
@FelixFXu You can consider to accept my answer (by marking the '✔' below the score) if it solved your issue.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.