gpt4 book ai didi

rust - 为什么在 Rust 中改变拥有的值和借用的引用是安全的?

转载 作者:行者123 更新时间:2023-12-03 08:13:32 24 4
gpt4 key购买 nike

How does Rust prevent data races when the owner of a value can read it while another thread changes it? ,我知道当我们想要改变一个对象时,即使使用拥有的值调用该方法,我也需要 &mut self

但是原始值怎么样,比如i32?我运行了这段代码:

fn change_aaa(bbb: &mut i32) {
*bbb = 3;
}

fn main() {
let mut aaa: i32 = 1;
change_aaa(&mut aaa); // somehow run this asynchronously
aaa = 2; // ... and will have data race here
}

我的问题是:

  1. 这在非并发情况下安全吗?根据The Rust Programming Language ,如果我们将拥有的值视为一个指针,那么根据以下规则它是不安全的,但是它可以编译。

    Two or more pointers access the same data at the same time.

    At least one of the pointers is being used to write to the data.

    There’s no mechanism being used to synchronize access to the data.

  2. 这在并发情况下安全吗?我尝试过,但我发现很难将 change_aaa(&mut aaa) 放入线程中,根据 Why can't std::thread::spawn accept arguments in Rust?How does Rust prevent data races when the owner of a value can read it while another thread changes it? 。然而,它的设计是很难或不可能做到这一点,还是只是因为我不熟悉 Rust?

最佳答案

change_aaa 的签名不允许将引用移动到另一个线程中。例如,您可能会想象 change_aaa() 的实现如下:

fn change_aaa(bbb: &mut i32) {
std::thread::spawn(move || {
std::thread::sleep(std::time::Duration::from_secs(1));
*bbb = 100; // ha ha ha - kaboom!
});
}

但是上面的代码无法编译。这是因为,脱糖后 lifetime elisionchange_aaa()的完整签名是:

fn change_aaa<'a>(bbb: &'a mut i32)

生命周期注释意味着 change_aaa 必须支持调用者选择的任何生命周期 'a 的引用,即使是非常短的生命周期,例如使引用无效的生命周期change_aaa() 返回后。这正是从 main() 调用 change_aaa() 的方式,可以将其脱糖为:

let mut aaa: i32 = 1;
{
let aaa_ref = &mut aaa;
change_aaa(aaa_ref);
// aaa_ref goes out of scope here, and we're free to mutate
// aaa as we please
}
aaa = 2; // ... and will have data race here

因此引用的生命周期很短,并且在分配给aaa之前结束。另一方面,thread::spawn() 需要一个与 'static 生命周期绑定(bind)的函数。这意味着传递给 thread::spawn() 的闭包必须仅包含拥有的数据,或者对 'static 数据的引用(保证数据持续到线程结束)程序)。由于 change_aaa() 接受生命周期短于 'staticbbb,因此它无法将 bbb 传递给 线程::spawn().

要掌握这一点,您可以尝试想出一些富有想象力的方法来编写 change_aaa() ,以便它在线程中写入 *bbb 。如果你成功地做到了这一点,你就会发现 rustc 中的一个错误。换句话说:

However, is it designed to be hard or impossible to do this, or just because I am unfamiliar with Rust?

它被设计为不可能做到这一点,除非通过明确设计以使其安全的类型(例如 Arc 来延长生命周期,以及 Mutex 来使写入数据竞争安全)。

关于rust - 为什么在 Rust 中改变拥有的值和借用的引用是安全的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70082733/

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