Accoding to cppreference.com:
The thread that intends to modify the variable has to
- acquire a std::mutex (typically via std::lock_guard)
- perform the modification while the lock is held
- execute notify_one or notify_all on the std::condition_variable (the lock does not need to be held for notification)
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.
I'm not quite understand, why modifying a atomic variable need to require an lock. Please see following code snippet:
static std::atomic_bool s_run {true};
static std::atomic_bool s_hasEvent {false};
static std::mutex s_mtx;
static std::condition_variabel s_cv;
// Thread A - the consumer thread
function threadA()
{
while (s_run)
{
{
std::unique_lock<std::mutex> lock(s_mtx);
s_cv.wait(lock, [this]{
return m_hasEvents.load(std::memory_order_relaxed);
});
}
// process event
event = lockfree_queue.pop();
..... code to process the event ....
}
}
// Thread B - publisher thread
function PushEvent(event)
{
lockfree_queque.push(event)
s_hasEvent.store(true, std::memory_order_release);
s_cv.notify_one();
}
In the PushEvent function, I do not acquire s_mtx because s_hasEvent is an atomic variable and the queue is lockfree. What is the problem w/o acquire the s_mtx lock?
s_hasEvents
by a mutex (which is also shared state) not the condvar. The publisher doesn't modify the condvar, it only callsnotify_one()
which doesn't need to be done while the mutex is locked. – Marquee