Please see the following code:
std::mutex mutex;
std::condition_variable cv;
std::atomic<bool> terminate;
// Worker thread routine
void work() {
    while( !terminate ) {
        {
            std::unique_lock<std::mutex> lg{ mutex };
            cv.wait(lg);
            // Do something
        }
        // Do something
    }
}
// This function is called from the main thread
void terminate_worker() {
    terminate = true;
    cv.notify_all();
    worker_thread.join();
}
Is the following scenario can happen?
- Worker thread is waiting for signals.
 - The main thread called 
terminate_worker();- The main thread set the atomic variable 
terminatetotrue, and then signaled to the worker thread. - Worker thread now wakes up, do its job and load from 
terminate. At this step, the change toterminatemade by the main thread is not yet seen, so the worker thread decides to wait for another signal. 
 - The main thread set the atomic variable 
 - Now deadlock occurs...
 
I wonder this is ever possible. As I understood, std::atomic only guarantees no race condition, but memory order is a different thing. Questions:
- Is this possible?
 - If this is not possible, is this possible if 
terminateis not an atomic variable but is simplybool? Or atomicity has nothing to do with this? - If this is possible, what should I do?
 
Thank you.
                        
I don't believe, what you describe is possible, as
cv.notify_all()afaik (please correct me if I'm wrong) synchronizes withwait(), so when the worker thread awakes, it will see the change toterminate.However:
A deadlock can happen the following way:
Worker thread (WT) determines that the
terminateflag is still false.The main thread (MT) sets the
terminateflag and callscv.notify_all().joinand blocks.cv.wait()) and blocks too.Solution:
While you don't have to hold a lock while you call cv.notify, you
terminate(even if it is an atomic)waithappen while you are holding the same lock.This is why there is a form of
waitthat performs this check just before it sends the thread to sleep.A corrected code (with minimal changes) could look like this: