访问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
相关产品推荐
相关产品推荐

