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

Rust中使用Tokio Mutex遭遇死锁问题求助

Rust中使用Tokio Mutex遭遇死锁问题求助

嗨,刚接触Rust异步并发遇到这种死锁问题太正常了,我来帮你拆解一下问题根源和解决办法~

问题根源:Tokio Mutex不支持重入

先理清楚你的代码执行流程,死锁的原因一下子就明了了:

  1. 在callback_query函数里,你先通过let hero_mut = hero.lock().await;拿到了hero这个Arc<Mutex<Hero>>的锁
  2. 接着你把同一个Arc<Mutex<Hero>>的克隆(hero_clone)传给了ability.perform方法
  3. 在perform方法里,你又调用hero.lock().await尝试再次获取锁

这里的核心坑点是:Tokio的tokio::sync::Mutex是不支持重入的。也就是说,同一个异步任务(task)如果已经持有了某个Mutex的锁,再次请求锁会导致当前任务被挂起,等待锁被释放——但持有锁的就是当前这个被挂起的任务,它根本没法释放锁,于是就陷入了永远等待的死锁状态。

解决办法

针对你的代码场景,有两个直接可行的解决方案,你可以根据代码结构选择:

方案1:复用已有的锁,避免重复请求

既然你在callback_query里已经拿到了hero的锁,完全可以直接把已锁定的Hero引用传给perform方法,不需要再在perform里重新加锁:

首先修改Ability::perform的签名,直接接受&mut Hero:

impl Ability {
    async fn perform(&self, bot: &Bot, game: Arc<Mutex<Game>>, target: Arc<Mutex<Player>>, hero: &mut Hero) -> bool {
        hero.damage(40);
        // 尽量缩小锁的持有范围,拿到需要的id后就释放Game的锁
        let game_id = game.lock().await.id;
        hero.send_message(bot, &game_id, "Take the khafang punchoo!".to_string()).await;
        true
    }
}

然后在callback_query里,直接把已锁定的hero_mut的引用传进去:

async fn callback_query(bot: Bot, callback_query: CallbackQuery) -> HandlerResult {
    // ... 省略其他代码 ...
    let mut hero_mut = hero.lock().await;
    let ability = hero_mut.abilities.get(ability).unwrap();
    let opponent = game_mut.get_next_turn();
    // 直接传&mut hero_mut,不需要再传hero_clone了
    ability.perform(&bot, game.clone(), opponent, &mut hero_mut).await;
    game_mut.next_turn(&bot).await;
    // ... 省略其他代码 ...
}

这样既解决了死锁问题,还能缩小锁的持有范围,提升并发效率。

方案2:改用支持重入的异步Mutex

如果你的代码结构实在需要在同一个任务里多次获取同一个锁,可以改用Tokio提供的ReentrantMutex(可重入锁),它允许同一个任务多次获取锁而不会死锁:

首先把你的Heroes类型定义里的Mutex换成ReentrantMutex:

use tokio::sync::ReentrantMutex;

pub type Heroes = [Arc<ReentrantMutex<Hero>>; 1];

ReentrantMutex的使用方式和Mutex几乎一致,但注意:可重入锁虽然能解决当前问题,但会掩盖一些设计上的冗余锁请求,建议优先用方案1,只有万不得已的时候再用重入锁。

额外小提醒

Rust异步里的Mutex和同步的std::sync::Mutex差异不小,比如Tokio的Mutex是为异步任务设计的,不能在阻塞代码里使用,而且默认不重入这个特性很容易踩坑。平时可以多看看Tokio官方文档里的并发章节,能帮你少踩很多这类新手坑~

备注:内容来源于stack exchange,提问作者Mmd

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 08:43:09