【发布时间】:2017-06-11 13:21:11
【问题描述】:
编码为cppreference.com:
打算修改变量的线程必须
- 获取 std::mutex(通常通过 std::lock_guard)
- 在持有锁时执行修改
- 在 std::condition_variable 上执行 notify_one 或 notify_all(通知不需要持有锁)
即使共享变量是原子的,也必须在互斥体下进行修改,才能正确地将修改发布到等待线程。
我不太明白,为什么修改原子变量需要锁。请看以下代码sn-p:
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();
}
在 PushEvent 函数中,我没有获取 s_mtx,因为 s_hasEvent 是一个原子变量,并且队列是无锁的。没有获取 s_mtx 锁有什么问题?
【问题讨论】:
-
条件变量是共享状态,因此必须用互斥锁保护。
-
问题是关于通过互斥锁(也是共享状态)而不是 condvar 来保护
s_hasEvents。发布者不修改 condvar,它只调用notify_one(),这在互斥锁锁定时不需要这样做。 -
@JonathanWakely 答案应该被接受
标签: c++ c++11 condition-variable