gpt4 book ai didi

rust - 非词汇生命周期借用检查器是否会过早释放锁定?

转载 作者:行者123 更新时间:2023-12-03 11:39:24 27 4
gpt4 key购买 nike

我读过What are non-lexical lifetimes?。使用非词法借用检查器,可以编译以下代码:

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
}

在上述情况下,这似乎是合理的,但是当涉及到互斥锁时,我们不希望过早释放它。

在下面的代码中,我想首先锁定共享结构,然后执行关闭,主要是为了避免死锁。但是,我不确定该锁是否会过早释放。

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是否会特别对待锁,以确保其使用生命周期可以延长到范围的尽头?我们是否必须像下面的代码那样显式地使用该变量,以避免过早丢失锁?

pub fn lock_and_execute(f: Box<Fn()>) {
let locked = SHARED.lock(); // - lifetime begins
f(); // |
drop(locked); // - lifetime ends
}

最佳答案

这里有一个误解:NLL(非词法生存期)影响借位检查,而不影响对象的实际生存期。

Rust广泛使用RAII1,因此许多对象(例如锁)的Drop实现都有副作用,这些副作用必须在执行流程中确定且可预测的点上发生。

NLL不会更改此类对象的生存期,因此它们的析构函数在与之前完全相同的时间执行:在其词法作用域的末尾,以相反的创建顺序执行。

NLL确实改变了对使用期限以进行借阅检查的编译器的理解。实际上,这不会导致任何代码更改。这纯粹是分析。进行此分析更加巧妙,以更好地识别使用引用的实际范围:

  • 在NLL之前,从创建引用到删除引用都被视为“使用中”,通常是其词法范围(因此得名)。
  • NLL,而不是:
  • 如果可能,尝试推迟“使用中”跨度的开始。
  • 以引用的最后使用结束“使用中”跨度。

  • 如果是 Ref<'a>(来自 RefCell),则 Ref<'a>将在词法作用域的末尾删除,此时它将使用对 RefCell的引用来减少计数器。

    NLL不会剥离抽象层,因此必须考虑到任何包含引用的对象(例如 Ref<'a>)都可以在其 Drop实现中访问该引用。结果,任何包含引用的对象(例如锁)都将强制NLL认为引用的“使用中”范围会一直扩展到被丢弃为止。

    1资源获取是初始化,其原始含义是,一旦执行了变量构造函数,它便获取了所需的资源,并且未处于半熟状态,这通常用来表示该变量的破坏将被释放。它拥有的任何资源。

    关于rust - 非词汇生命周期借用检查器是否会过早释放锁定?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63122567/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com