当谓词检查互斥锁外更新的标志时,加空锁作用域能否避免条件变量通知丢失?
空锁作用域能避免条件变量通知丢失吗?
咱们先把问题掰明白:当条件变量的等待谓词依赖于互斥锁外部更新的原子标志时(就像你代码里的atomicFlag),在调用notify_all()之前加一个空的lock_guard作用域,真的能防止通知丢失吗?答案是能,咱们结合你的代码一步步分析。
先看你的示例代码
#include <condition_variable> #include <mutex> #include <atomic> #include <functional> #include <thread> class TaskScheduler { public: static void someMethod(std::function<bool(void)>&& pred) { _wait(std::move(pred)); } static void notify() { { std::lock_guard<std::mutex> lock(waitMutex); } // 这个空锁作用域是关键 waitCV.notify_all(); } private: static std::mutex waitMutex; static std::condition_variable waitCV; static void _wait(std::function<bool(void)>&& pred) { std::unique_lock<std::mutex> lock(waitMutex); waitCV.wait(lock, [&](){return pred();}); } }; std::mutex TaskScheduler::waitMutex; std::condition_variable TaskScheduler::waitCV; std::atomic<bool> waiting{false}; std::atomic<bool> atomicFlag{false}; void thread1() { TaskScheduler::someMethod([&](){waiting = true; return atomicFlag.load();}); } void thread2() { // 这段代码是在thread1等待时调用的 atomicFlag = true; TaskScheduler::notify(); } int main(int argc, char **argv) { std::thread th1([&](){thread1();}); while (!waiting) {}; // 确保thread1进入等待状态 std::thread th2([&](){thread2();}); th2.join(); th1.join(); }
为什么空锁能解决通知丢失?
首先得搞懂通知丢失的本质:它发生在这种倒霉时序下——
- 线程A(thread1)检查谓词,发现
atomicFlag是false - 线程B(thread2)立刻把
atomicFlag设为true,然后调用notify_all() - 线程A才刚进入
wait()状态,这时候它已经错过了通知,会一直卡着等下去
那这个空锁作用域怎么破局?核心是互斥锁的同步特性:
- 当thread2加锁再解锁
waitMutex时,这个操作会强制把atomicFlag = true的写操作同步到主内存,确保所有后续获取这个锁的线程都能看到最新值。 - 更重要的是,这个空锁会强制线程间的执行顺序:thread2必须先完成
atomicFlag的写入,再解锁waitMutex;而thread1在wait()的流程中,要么已经持有锁检查过谓词,要么会在thread2解锁后才拿到锁去检查——这就彻底堵死了“thread2先通知,thread1后进入等待”的可能性。
换句话说,这个空锁给线程间建立了明确的happens-before关系:
- thread2的
atomicFlag = true一定发生在它解锁waitMutex之前 - thread2解锁
waitMutex一定发生在thread1重新获取锁检查谓词之前 - 所以thread1要么在第一次检查谓词时就看到
atomicFlag为true直接返回,要么进入等待后能收到thread2的通知,绝不会出现通知丢失的情况。
额外提一句你的代码细节
你在谓词里写了waiting = true,这个操作是安全的——因为wait()在调用谓词时是持有waitMutex的,所以多个线程调用也不会有竞态问题,这点处理得很到位。
内容的提问来源于stack exchange,提问作者user3187878
相关产品推荐
相关产品推荐

