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

Rust中Dashmap调用remove死锁:为何使用owned值仍持有map引用

死锁原因解释

死锁的核心是Rust的临时对象生命周期规则,完全符合Dashmap文档提到的「持有map引用时调用remove会死锁」的约定:

  • DashMap的iter()方法返回的迭代器会持有对应数据分片的读锁,直到迭代器本身被销毁才会释放锁
  • Rust默认规则下,同一个语句内产生的所有临时对象,会等到整个语句完全执行完毕后才会统一销毁,不会在子表达式计算完成后提前销毁。

对应到你的代码:
if let Some(i) = map.iter().next().map(|k| k.key().to_string()) 属于同一个表达式语句,map.iter()产生的迭代器是该语句的临时对象:

  1. 迭代器先拿到分片读锁,后续计算得到了owned类型的字符串i
  2. 但此时迭代器还没有被销毁,读锁仍然被持有
  3. 进入if代码块调用map.remove(&i)时,remove需要获取同一分片的写锁,读写锁冲突直接导致死锁。

为什么提前存储变量就正常?

当你把迭代求值的逻辑单独放到独立的let语句时:

// 迭代逻辑单独作为一条语句
let opt_i = map.iter().next().map(|k| k.key().to_string());
if let Some(i) = opt_i {
    map.remove(&i);
}

map.iter()产生的迭代器是let opt_i = ...这条语句的临时对象,该语句执行完成后迭代器就会被销毁,读锁随之释放,后续调用remove拿写锁不会有冲突,自然不会死锁。

你也可以通过手动加花括号限制临时对象生命周期来解决问题:

if let Some(i) = {
    // 迭代器生命周期被限制在花括号内,花括号执行完立刻销毁
    map.iter().next().map(|k| k.key().to_string())
} {
    map.remove(&i);
}

内容的提问来源于stack exchange,提问作者J. Doe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 07:36:07