32

I am reading aboutstd::condition_variable and I don't understand this:

Even if the shared variable is atomic, it must be modified under the mutex in order to correctly publish the modification to the waiting thread.

Why a shared atomic variable is not properly published if it is not modified under mutex? How to understand this statement?

The following quote fromstd::atomic<T>) seems to contradict to the the above statement:

If one thread writes to an atomic object while another thread reads from it, the behavior is well-defined (see memory model for details on data races).

Dr. Gut's user avatar
Dr. Gut
3,50714 silver badges33 bronze badges
askedJul 1, 2016 at 14:22
5
  • 1
    std::condition_variable andstd::atomic are two different things.CommentedJul 1, 2016 at 14:30
  • 1
    I suppose it's because the waiting thread synchronizes via the mutex (otherwise it couldn't be "waiting") and not via the atomic variable.CommentedJul 1, 2016 at 14:30
  • 5
    It's about the final example instackoverflow.com/a/32978267/2756719CommentedJul 1, 2016 at 14:33
  • Well if thestd::condition_variable has any other internal state then that needs to be protected(synchronized).CommentedJul 1, 2016 at 14:33
  • Atomicity does not necessarily means synchronized. Seeshan-weiqiang.github.io/2024/04/27/…CommentedApr 27, 2024 at 11:49

1 Answer1

43
+50

Consider this example:

std::atomic_bool proceed = false;std::mutex m;std::condition_variable cv;std::thread t([&m,&cv,&proceed](){    std::unique_lock<std::mutex> l(m);    while(!proceed) {        hardWork();        cv.wait(l);    }});proceed = true;cv.notify_one();t.join();

Here the atomic shared dataproceed is modified without the use of a mutex, after which notification is sent to the condition variable. But it is possible that at the instant that the notification is sent, the threadt is not waiting oncv: instead it is insidehardWork() having checkedproceed just before that and found it to be false. The notification is missed. Whent completeshardWork, it will resume the wait (presumably forever).

Had the main thread locked the mutex before modifying the shared dataproceed, the situation would have been avoided.

I think this is the situation in mind when saying "Even if the shared variable is atomic, it must be modified under the mutex in order to correctly publish the modification to the waiting thread."

Dr. Gut's user avatar
Dr. Gut
3,50714 silver badges33 bronze badges
answeredJul 1, 2016 at 14:54
Smeeheey's user avatar
Sign up to request clarification or add additional context in comments.

9 Comments

This can happen even withouthardWork. You can checkproceed, find it to be false, thenproceed can be set totrue, thennotify_one can be called, and then you can callwait. Again, you'd be waiting for something that already happened. The entire logic of condition variables is that they work in conjunction with the mutex that protects the shared state to provide an atomic "unlock and wait" operation.
@DavidSchwartz What if addlock_guard{m} betweenproceed = true; andcv.notify_one();? If do that,notify_one will not be called beforewait.
@macomphy But then it makes no difference whetherproceed is atomic or not because it is never accessed without holding the mutex.
@DavidSchwartz Sorry, maybe I didn't express it clearly enough. I mean something like this: :godbolt.org/z/xcM1oqKjz.
You should not need to actually hold the mutex while modifying the atomic, it should be enough to lock the mutexafter modifyingproceed and then unlocking it again directly, before signalling the CV
|

Your Answer

Sign up orlog in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

By clicking “Post Your Answer”, you agree to ourterms of service and acknowledge you have read ourprivacy policy.