问题描述
我已阅读什么是非词汇生存期?.使用非词汇借阅检查器,可以编译以下代码:
I've read What are non-lexical lifetimes?. With the non-lexical borrow checker, the following code compiles:
fn main() {
let mut scores = vec![1, 2, 3];
let score = &scores[0]; // borrows `scores`, but never used
// its lifetime can end here
scores.push(4); // borrows `scores` mutably, and succeeds
}
在上述情况下,这似乎是合理的,但是当涉及到互斥锁时,我们不希望它被过早释放.
It seems reasonable in the case above, but when it comes to a mutex lock, we don't want it to be released prematurely.
在以下代码中,我想首先锁定共享结构,然后执行关闭,主要是为了避免死锁.但是,我不确定该锁是否会过早释放.
In the following code, I would like to lock a shared structure first and then execute a closure, mainly to avoid deadlock. However, I'm not sure if the lock will be released prematurely.
use lazy_static::lazy_static; // 1.3.0
use std::sync::Mutex;
struct Something;
lazy_static! {
static ref SHARED: Mutex<Something> = Mutex::new(Something);
}
pub fn lock_and_execute(f: Box<Fn()>) {
let _locked = SHARED.lock(); // `_locked` is never used.
// does its lifetime end here?
f();
}
Rust是否特别对待锁,以确保其寿命可以延长到范围的尽头?我们是否必须像下面的代码那样显式地使用该变量以避免过早丢失锁?
Does Rust treat locks specially, so that their lifetimes are guaranteed to extend to the end of their scope? Must we use that variable explicitly to avoid premature dropping of the lock, like in the following code?
pub fn lock_and_execute(f: Box<Fn()>) {
let locked = SHARED.lock(); // - lifetime begins
f(); // |
drop(locked); // - lifetime ends
}
推荐答案
这里有一个误解:NLL(非词法生存期)影响借阅检查,而不是实际的 lifetime .
There is a misunderstanding here: NLL (non-lexical lifetimes) affects the borrow-checks, not the actual lifetime of the objects.
Rust广泛使用RAII ,因此,许多对象(例如锁)的Drop
实现都有必须出现在在执行流程中确定和可预测的要点.
Rust uses RAII extensively, and thus the Drop
implementation of a number of objects, such as locks, has side-effects which have to occur at a well-determined and predictable point in the flow of execution.
NLL不会更改此类对象的生存期,因此它们的析构函数在与之前完全相同的时间执行:在其词法作用域的末尾,以相反的顺序创建.
NLL did NOT change the lifetime of such objects, and therefore their destructor is executed at exactly the same point that it was before: at the end of their lexical scope, in reverse order of creation.
NLL确实改变了使用期限的编译器理解,以进行借阅检查.实际上,这不会导致任何代码更改.这纯粹是分析.进行这种分析更加巧妙,以更好地识别使用引用的实际范围:
NLL did change the understanding of the compiler of the use of lifetimes for the purpose of borrow-checking. This does not, actually, cause any code change; this is purely analysis. This analysis was made more clever, to better recognize the actual scope in which a reference is used:
- 在NLL之前,从创建引用到删除引用都被视为使用中",通常是其词法范围(因此得名).
- NLL,而不是:
- 如果可能的话,尝试推迟使用中"跨度的开始.
- 以引用的最后使用结束使用中"范围.
- Prior to NLL, a reference was considered "in use" from the moment it was created to the moment it was dropped, generally its lexical scope (hence the name).
- NLL, instead:
- Tries to defer the start of the "in use" span, if possible.
- Ends the "in use" span with the last use of the reference.
对于
Ref<'a>
(来自RefCell
),Ref<'a>
将在词法作用域的末尾删除,这时它将使用对RefCell
减少计数器.In the case of a
Ref<'a>
(fromRefCell
), theRef<'a>
will be dropped at the end of the lexical scope, at which point it will use the reference toRefCell
to decrement the counter.NLL不会剥离抽象层,因此必须认为包含引用(例如
Ref<'a>
)的任何对象 都可以在其实施.结果,任何包含引用的对象(例如锁)都将强制NLL认为引用的使用中"范围会一直扩展到被丢弃为止.NLL does not peel away layers of abstractions, so must consider that any object containing a reference (such as
Ref<'a>
) may access said reference in itsDrop
implementation. As a result, any object that contains a reference, such as a lock, will force NLL to consider that the "in use" span of the reference extends until they are dropped.资源获取是初始化,其原始含义是,一旦执行了变量构造函数,它便已获取了所需的资源,并且未处于半熟状态.通常用来表示破坏该变量将释放它拥有的所有资源.
这篇关于非词汇生命周期借用检查器是否会过早释放锁定?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!