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

访问HashSet时触发死锁,为何仅Tokio异步互斥锁可正常运行?

死锁排查:同步RwLock阻塞,异步RwLock正常工作

我在异步代码中使用同步RwLock(std::sync::RwLock或parking_lot::RwLock)时遇到了死锁,代码完全无法运行,但换成Tokio的异步RwLock就一切正常。

我原本猜测是在await调用点持有了锁,但反复检查后确认没有这种情况,显然哪里出了问题但我还没找到。

简化后的代码

连接处理逻辑

每个连接都会启动一个Tokio任务,在任务内部调用并await这个run方法:

pub async fn run(&mut self) -> Result<(), ConnectionError> {
    self.handshake().await?;
    loop {
        let msg = self
            .connection
            .next()
            .await
            .ok_or(ConnectionError::NoMessage)??; 
        let r = handle_message(msg)?;
        if let Some(r) = r {
            self.connection.send(r).await?;
        }
    }
}

出问题的处理函数

这个函数被handle_message调用,是唯一操作IDs的函数:

fn handle_request_by_id(id: u64) -> Result<Self, DecodeError> {
    {
        if IDs.read().contains(id) {
            return Ok(Self::default());
        }
    }

    {
        IDs.write().insert(id);
    }

    //...rest of the logic
}

全局锁定义

这里用的是parking_lot的RwLock,换成标准库的也会出现同样问题:

pub static IDs: Lazy<RwLock<HashSet<u64>>> =
    Lazy::new(|| RwLock::new(HashSet::with_capacity(4_000_000)));

排查情况

  • handle_request_by_id是唯一操作IDs的函数,没有其他地方长时间持有锁
  • 我认为自己遵循了Tokio文档中的规则:

As a rule of thumb, using a synchronous mutex from within asynchronous code is fine as long as contention remains low and the lock is not held across calls to .await

但问题依然存在,换成Tokio异步RwLock就完全正常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 12:25:20