当一个值的所有者可以读取它而另一个线程更改它时,Rust 如何防止数据竞争?

Jul*_*fer 2 concurrency rust

Rust 书在参考文献和借用中陈述了以下内容

当我们有一个不可变的引用时,我们也不能有一个可变的引用。不可变引用的用户不希望值突然从它们下面改变!但是,多个不可变引用是可以的,因为没有人只是在读取数据,因此无法影响其他人对数据的读取。

但是所有者可以读取数据,而另一个线程通过可变借用更改值,对吗?那么我们是不是又遇到了通常的问题,或者我在哪里误解了潜在的概念?

E_n*_*ate 6

所有者可以读取数据,而另一个线程通过可变借用更改值,对吗?

这是不正确的,甚至是否涉及多个线程都无关紧要。

您可以在以下示例 ( Playground ) 中亲自查看。这是一个x被修改的字符串值,同时保留对相同值的引用y

let mut x = "123".to_string();
let y = &mut x;

x.push_str("456");

println!("y = {}", y);
Run Code Online (Sandbox Code Playgroud)

这无法编译:

let mut x = "123".to_string();
let y = &mut x;

x.push_str("456");

println!("y = {}", y);
Run Code Online (Sandbox Code Playgroud)

当我们尝试调用push_str一个接收 的方法时,&mut self假定当场构建了对该值的新可变引用。由于x已经在该范围内借用,这是非法的。

现在,您甚至可以考虑重新分配而不是调用期望&mut self. 不过,机会很大:

error[E0499]: cannot borrow `x` as mutable more than once at a time
 --> src/main.rs:5:5
  |
3 |     let y = &mut x;
  |             ------ first mutable borrow occurs here
4 |     
5 |     x.push_str("456");
  |     ^ second mutable borrow occurs here
6 | 
7 |     println!("y = {}", y);
  |                        - first borrow later used here
Run Code Online (Sandbox Code Playgroud)
let mut x = "123".to_string();
let y = &mut x;

x = "321".to_string();

println!("y = {}", y);
Run Code Online (Sandbox Code Playgroud)

借用的值也不能重新分配。

总而言之,价值的所有者仍然受到任何借入方式的限制。如果值是永久借用的,则所有者也可以具有不可变的访问权限,但只要借用就位,就永远不能写入移动值。当该值被可变地借用时,在删除该引用之前,所有者无法对该值执行任何操作。

  • 这非常有帮助并解决了一个问题,我至少挣扎了三个星期。我想知道您的答案是否适合集成到各种 Rust 资源之一中,因为它们都没有让我掌握您在答案的最后一段中描述的概念:) (2认同)