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

时间:2019-04-15 11:16:44

标签: concurrency rust

Rust书在References and borrowing

中指出以下内容
  

当我们拥有不变的引用时,我们也不能具有可变的引用。不变引用的用户不会期望值从它们下面突然改变!但是,可以使用多个不可变的引用,因为没有人正在读取数据,就不会影响其他任何人对数据的读取。

但是所有者可以读取数据,而另一个线程通过可变借位更改值,对吗?难道我们就不会再遇到通常的问题了吗?或者我在哪里误解了基本概念?

1 个答案:

答案 0 :(得分:3)

  

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

这是错误的,甚至是否涉及多个线程也没关系。

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

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

x.push_str("456");

println!("y = {}", y);

无法编译:

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

在我们尝试调用push_str(一种接收&mut self的方法)时,假定会在现场建立对该值的新可变引用。由于x已在该范围内借用,因此这是非法的。

现在,您甚至可以考虑重新分配而不是调用期望&mut self的方法。仍然有机会:

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

x = "321".to_string();

println!("y = {}", y);
error[E0506]: cannot assign to `x` because it is borrowed
 --> src/main.rs:5:5
  |
3 |     let y = &mut x;
  |             ------ borrow of `x` occurs here
4 |     
5 |     x = "321".to_string();
  |     ^ assignment to borrowed `x` occurs here
6 | 
7 |     println!("y = {}", y);
  |                        - borrow later used here

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

总而言之,无论是哪种借贷,价值的所有者仍然受到限制。如果该值是一成不变地借用的,则所有者也可以具有不可变的访问权限,但是只要借用到位,就永远不能将该值写入 moved 。 当该值是可变的借入时,所有者将无法使用该值执行任何操作,直到删除该引用为止。