循环声明内的互斥锁

abc*_*bet 4 mutex rust

根据我的理解,获得互斥体的锁定,然后立即在受保护的结构上调用函数,而无需为 MutexGuard 声明单独的变量,一旦函数调用完成,就会释放此保护。

我的问题是,在循环声明中获取锁时是否也是这种情况,如下所示:

for ele in mtx.lock().await.clone() {
    // do something requiring lock on mtx
}
Run Code Online (Sandbox Code Playgroud)

这里的期望是,一旦clone调用完成,mtx 上的锁就会被释放,并且可以在循环内重新获取。是这样吗?如果不是,为什么情况并非如此?

Sve*_*ach 6

不,事实并非如此。在迭代器表达式中创建的临时对象将一直存在到 for 循环结束,并且互斥锁保护只会在循环之后被删除。

临时变量通常在语句末尾被删除。您可以在有关临时作用域的文档中查看完整规则:

除了生命周期扩展之外,表达式的临时作用域是包含该表达式的最小作用域,并且是以下之一:

  • 整个函数体。
  • 一份声明。
  • if,while或表达式的主体loop
  • else表达式块if
  • or 表达式或if守卫的条件表达式。whilematch
  • 火柴臂的表达式。
  • 惰性布尔表达式的第二个操作数。

这些规则涵盖了许多微妙的极端情况,因此很难给出一个简短的总结为什么该语言是这样设计的。特别是对于 for 循环,如果迭代器表达式内创建的临时变量立即被删除,那将是非常烦人的,因为这样的事情会导致借用检查器错误:

for x in my_vec.iter().filter(|&&y| y != 0) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

如果编译器只保留迭代器表达式的结果,则返回的迭代器my_vec.iter()将立即被删除,这当然是不希望的。