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

使用Rust的Condvar定期唤醒线程遇到的异常问题

问题分析与修复

你的代码无法正常运行有两个核心问题:

  1. 子线程长期持有Mutex锁
    子线程在loop外就获取了started的锁,整个循环过程中都没有释放锁。主线程调用cvar.wait(started)时,虽然会暂时释放锁,但被唤醒后需要重新获取锁才能继续执行——可子线程一直占着锁不放,主线程根本拿不到,自然无法打印内容。

  2. Condvar的使用不符合设计逻辑
    Condvar的设计是基于共享状态变化来唤醒等待线程,你的代码里既不需要维护状态值,也没在唤醒后做状态重置,同时子线程持锁的行为彻底阻塞了主线程的锁获取路径。

修复后的代码(无需状态值的定期唤醒)

如果只是需要定期唤醒主线程,无需维护额外状态,可以这样调整:

use std::sync::{Arc, Mutex, Condvar};
use std::thread;

fn main() {
    let pair = Arc::new((Mutex::new(()), Condvar::new()));
    let pair2 = Arc::clone(&pair);
    
    thread::spawn(move|| {
        let (_lock, cvar) = &*pair2;
        loop {
            // Condvar的notify操作不需要持有对应Mutex锁
            cvar.notify_one();
            thread::sleep(std::time::Duration::from_millis(20));
        }
    });
    
    let (lock, cvar) = &*pair;
    let mut guard = lock.lock().unwrap();
    loop {
        // wait会自动释放锁,被唤醒后重新获取锁
        guard = cvar.wait(guard).unwrap();
        println!("done");
    }
}

关键调整点

  • 子线程不再持有Mutex锁:因为不需要修改共享状态,直接调用notify_one()即可,Condvar的通知操作本身不需要持有对应锁。
  • 共享状态改为空元组():既然不需要维护唤醒相关的状态,用空元组占位满足类型要求即可。
  • 主线程保持标准wait逻辑:wait方法会自动释放锁,被唤醒后重新获取锁,确保线程安全。

进阶优化(避免虚假唤醒)

如果需要确保只有被主动notify才执行逻辑(避免Condvar的虚假唤醒问题),可以配合一个简单的状态标记:

use std::sync::{Arc, Mutex, Condvar};
use std::thread;

fn main() {
    let pair = Arc::new((Mutex::new(false), Condvar::new()));
    let pair2 = Arc::clone(&pair);
    
    thread::spawn(move|| {
        let (lock, cvar) = &*pair2;
        loop {
            let mut state = lock.lock().unwrap();
            *state = true;
            cvar.notify_one();
            drop(state); // 主动释放锁,让主线程能获取
            thread::sleep(std::time::Duration::from_millis(20));
        }
    });
    
    let (lock, cvar) = &*pair;
    let mut started = lock.lock().unwrap();
    loop {
        // 循环检查状态,过滤虚假唤醒
        while !*started {
            started = cvar.wait(started).unwrap();
        }
        println!("done");
        *started = false; // 重置状态,等待下一次唤醒
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 21:36:28