You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

并发原语:如何无忙等待实现仅执行最新触发任务的调度

并发问题无忙等实现方案

核心采用原子状态位+互斥锁+条件变量的组合实现,既规避忙等待,又不会丢失通知,同时天然满足多次触发合并的调度规则。

状态定义

共享三个同步原语:

  • atomic_bool should_run = false:待执行任务标记,和最初CAS实现语义一致,值为true代表存在待处理的工作请求
  • mutex mtx:配合条件变量使用的互斥锁
  • condition_variable cv:用于线程阻塞/唤醒的条件变量

实现代码

伪代码和原有实现风格保持一致:

// 共享状态初始化
mutex mtx
condition_variable cv
atomic_bool should_run = false

<线程A 触发逻辑>
if (需要启动工作) {
    // 原子方式将标记设为true,返回设置前的旧值
    old_state = should_run.exchange(true)
    // 仅当之前没有待处理任务时才发送唤醒信号,避免冗余系统调用
    if (old_state == false) {
        lock(mtx)
        cv.notify_one()
        unlock(mtx)
    }
}

<线程B 执行逻辑>
loop {
    lock(mtx)
    // 阻塞等待直到待执行标记为true,wait内部会自动处理虚假唤醒
    cv.wait(mtx, []() { return should_run.load() })
    // 拿到执行权后立刻清空标记,开始处理任务
    should_run.store(false)
    unlock(mtx)
    // 执行任务期间不持有锁,不阻塞线程A发通知
    do_work()
}

规则匹配验证

  • 无忙等:线程B无待处理任务时会完全阻塞在cv.wait调用上,不占用CPU时间片,不存在轮询开销
  • 不丢通知:所有触发请求首先会写入should_run状态位持久化,即使发送通知时线程B正在执行do_work()、未处于wait阻塞状态,等B完成当前任务回到wait检查点时,会直接检测到标记为true,无需等待新通知就会执行下一轮任务
  • 自动合并多次触发:线程B执行任务期间,无论线程A触发多少次通知,should_run只会保持true状态,不会累计计数,B完成当前任务后仅会执行1次新工作,完全符合“累计N次通知仅执行1次”的要求

实现细节说明

线程A侧仅在should_run从false切到true的时候发送唤醒信号,是因为如果旧值已经为true,说明已经有未处理的任务、唤醒信号已经发送过,重复调用notify_one不会带来任何收益,只会增加不必要的系统调用开销。
另外cv.wait传入谓词判断的写法,会自动处理条件变量常见的虚假唤醒问题,不需要额外加循环判断。


内容的提问来源于stack exchange,提问作者linkedin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 02:39:32