无锁多生产者单消费者场景下避免丢失唤醒的方案探讨
解决无锁MPSC队列的条件变量唤醒丢失问题
针对你遇到的唤醒丢失场景,这里提供两个无需阻塞数据线程的解决方案,完全符合低延迟需求:
方案一:原子状态标记+条件变量谓词检查
核心思路是用原子变量标记队列是否存在未处理任务,让工作线程进入休眠前做双重检查,避免错过窗口内到来的任务。
代码实现:
#include <atomic> #include <mutex> #include <condition_variable> std::atomic<bool> has_pending_tasks = false; std::mutex mutex_; std::condition_variable cv_; MpscJobQueue queue_; // 工作线程逻辑 while (true) { // 处理队列中所有现有任务 while (!queue_.empty()) { process(queue_.pop()); } // 标记当前无待处理任务(内存序确保队列操作可见) has_pending_tasks.store(false, std::memory_order_release); std::unique_lock<std::mutex> lock(mutex_); // 条件变量的谓词会再次检查状态: // 如果数据线程在工作线程设置标记后、进入休眠前推送了任务,直接退出等待 cv_.wait(lock, [&]() { return has_pending_tasks.load(std::memory_order_acquire); }); } // 数据线程逻辑 queue_.push(myData); // 标记有新任务,内存序确保队列写入对工作线程可见 has_pending_tasks.store(true, std::memory_order_release); cv_.notify_one();
方案优势:
- 数据线程全程不触碰互斥锁,完全不会被挂起,满足低延迟要求;
- 彻底避免唤醒丢失:即使notify发生在工作线程进入wait之前,谓词检查也能发现新任务,工作线程会立刻回到外层循环处理队列;
- 内存序的使用确保了队列操作和状态标记的可见性,无内存一致性问题。
方案二:自旋锁+std::condition_variable_any
利用自旋锁用户态忙等的特性,既保证工作线程进入休眠前的窗口不会错过任务,又不会让数据线程陷入内核态挂起。
代码实现:
#include <atomic> #include <condition_variable> // 轻量自旋锁实现 struct SpinLock { std::atomic<bool> locked = false; void lock() { // 忙等时加入pause指令减少CPU空转(x86平台) while (locked.exchange(true, std::memory_order_acquire)) { __builtin_ia32_pause(); } } void unlock() { locked.store(false, std::memory_order_release); } }; SpinLock spin_lock_; std::condition_variable_any cv_; MpscJobQueue queue_; // 工作线程逻辑 while (true) { while (!queue_.empty()) { process(queue_.pop()); } std::unique_lock<SpinLock> lock(spin_lock_); // 谓词直接检查队列是否为空 cv_.wait(lock, [&]() { return !queue_.empty(); }); } // 数据线程逻辑 queue_.push(myData); { // 自旋锁的忙等不会导致线程挂起,延迟可忽略 std::lock_guard<SpinLock> lock(spin_lock_); } cv_.notify_one();
方案优势:
- 数据线程仅在极端情况(工作线程刚好处于退出内层循环到进入wait的窗口)下会短暂自旋,不会被内核挂起,符合低延迟要求;
- 工作线程休眠时会释放自旋锁,不影响数据线程后续操作;
- 逻辑更直观,直接通过锁同步工作线程进入休眠的时机和数据线程的notify时机。
方案对比
- 优先选择原子状态标记方案,它的开销更低,数据线程完全无锁,适配你的场景;
- 自旋锁方案适合需要更直观同步逻辑的场景,虽然数据线程有极短暂的忙等,但对你的低延迟需求来说完全可接受。
内容的提问来源于stack exchange,提问作者Michael Jung
相关产品推荐
相关产品推荐

