C++实现可临时暂停的并发循环,确保启停操作返回时工作线程未执行任务
原实现的问题
你当前的实现存在的核心竞态是:调用disable_worker将enabled设为false后直接返回,但此时工作线程可能已经通过了条件变量的检查,正在执行任务逻辑或处于休眠流程,无法保证返回时工作线程未执行任务。
解决方案
我们可以通过新增状态标识和主线程等待的逻辑实现无竞态的要求,完整实现代码如下:
#include <chrono> #include <condition_variable> #include <mutex> #include <thread> using namespace std::literals::chrono_literals; // 全局状态变量,所有访问都受mtx保护 bool enabled = true; bool worker_paused = false; std::mutex mtx; std::condition_variable worker_cond; // 工作线程等待启用的条件变量 std::condition_variable main_cond; // 主线程等待工作线程暂停的条件变量 void disable_worker() { std::unique_lock<std::mutex> lock(mtx); if (!enabled) { // 已经是禁用状态,直接返回 return; } enabled = false; // 等待工作线程进入暂停状态 main_cond.wait(lock, []{ return worker_paused; }); } void enable_worker() { std::unique_lock<std::mutex> lock(mtx); if (enabled) { // 已经是启用状态,直接返回 return; } enabled = true; // 唤醒阻塞的工作线程 worker_cond.notify_one(); // 等待工作线程完成单次任务回到暂停状态 main_cond.wait(lock, []{ return worker_paused; }); } void do_work() { for (;;) { std::unique_lock<std::mutex> lock(mtx); // 标记自身进入暂停状态,通知可能等待的主线程 worker_paused = true; main_cond.notify_all(); // 等待启用信号 worker_cond.wait(lock, []{ return enabled; }); worker_paused = false; // 提前释放锁,避免执行任务时长期持有锁影响主线程操作 lock.unlock(); // 任务执行逻辑,无锁状态 // ... do some work ... // 固定时长休眠 std::this_thread::sleep_for(100ms); } } int main() { std::thread t(do_work); // ... 按需调用enable_worker/disable_worker ... t.join(); return 0; }
逻辑说明
- 状态保护:所有对全局状态的访问都在互斥锁
mtx的保护下进行,不存在数据竞争。 - disable逻辑:调用
disable_worker时,先将enabled设为false,再阻塞等待worker_paused状态为真:此时工作线程会完成当前正在执行的任务+休眠流程,回到循环头部后标记worker_paused为真并通知主线程,随后进入条件变量阻塞状态,主线程收到通知后即可安全返回。 - enable逻辑:调用
enable_worker时,先将enabled设为true唤醒工作线程,再阻塞等待worker_paused状态为真:工作线程被唤醒后完成单次任务+休眠流程,回到循环头部标记worker_paused为真并通知主线程,主线程收到通知后返回,此时工作线程未进入下一次任务执行流程,符合要求。 - 无死锁保证:所有条件变量等待都配套了谓词检查,避免虚假唤醒导致的逻辑异常,且锁的持有范围仅覆盖状态操作,不会长期阻塞。
内容的提问来源于stack exchange,提问作者peter
相关产品推荐
相关产品推荐

