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

使用Arc和Mutex时Rust线程间共享状态更新失效问题排查

问题分析

你的问题核心在于**stdout锁的持有时间过长**,导致两个线程的执行互相阻塞:

  • handle_client线程在整个输入循环开始时就获取了stdout的锁,并且在循环全程持有该锁未释放。
  • do_broadcast线程每次循环都需要获取stdout锁才能执行broadcast,但由于handle_client一直持有锁,do_broadcast会被持续阻塞,直到handle_client退出循环、释放锁后才能执行一次broadcast——这就是只有handle_client退出时才能看到更新的原因。
修复方案

调整handle_client线程中stdout锁的获取时机,将其从循环外移到循环内部,每次处理单个输入时临时获取锁,处理完成后自动释放:

let handle_client = thread::spawn(move || {
    let stdin = io::stdin().lock();
    let inputs = serde_json::Deserializer::from_reader(stdin).into_iter::<Message<Payload>>();

    for input in inputs {
        thread::sleep(Duration::from_millis(1));
        let input = input.context("cannot deserialize the input message").unwrap();
        // 每次处理输入时才获取stdout锁,执行完step后自动释放
        let mut stdout = io::stdout().lock();
        _node.lock().unwrap().step(input, &mut stdout).unwrap();
    }
});

同时建议调整do_broadcast线程的锁获取顺序,先获取Node的锁再获取stdout锁,统一锁的获取顺序能避免潜在的死锁风险:

let do_broadcast = thread::spawn(move || loop {
    // 先获取Node锁,再获取stdout锁
    let mut node_guard = _node.lock().unwrap();
    let mut stdout = io::stdout().lock();
    node_guard.broadcast(&mut stdout);
    // 离开当前作用域后,两个锁会自动释放
    thread::sleep(Duration::from_millis(100));
});
额外优化建议
  • 避免在持有锁的状态下执行长时间操作,当前代码中的sleep都在锁释放后执行,这点符合最佳实践。
  • 生产环境中建议替换unwrap(),改用match或if let做更优雅的错误处理,避免因锁获取失败、反序列化失败等情况直接导致程序panic。

内容的提问来源于stack exchange,提问作者Harsh Kumar Chourasia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 16:29:56