Rust所有权系统核心原则
- 所有权:每个值在Rust中都有一个变量,称为该值的所有者。当所有者离开作用域时,该值将被释放。例如:
{
let s = String::from("hello"); // s是"hello"这个字符串的所有者
} // s离开作用域,字符串被释放
- 独占性:一个值在同一时间只能有一个所有者。这意味着在任何时候,只能有一个变量绑定到该值。例如:
let s1 = String::from("hello");
let s2 = s1; // s1的所有权转移给s2,此时s1不再有效
// println!("{}", s1); // 这行代码会报错,因为s1已失效
- 借用:可以在不获取所有权的情况下使用值,称为借用。分为不可变借用和可变借用。不可变借用允许多个同时存在,但可变借用同一时间只能有一个。例如:
let s = String::from("hello");
let len = calculate_length(&s); // 不可变借用
println!("The length of '{}' is {}.", s, len);
fn calculate_length(s: &String) -> usize {
s.len()
}
let mut s = String::from("hello");
let r1 = &mut s; // 可变借用
*r1 = String::from("world");
// let r2 = &mut s; // 这行代码会报错,因为同一时间只能有一个可变借用
防止数据竞争
- 数据竞争条件:数据竞争发生在多个线程同时访问同一内存位置,并且至少有一个是写操作,且没有适当的同步机制。
- Rust的防止方式:
- 所有权和独占性:由于同一时间只有一个所有者,避免了多个所有者同时写数据的情况。例如,当所有权转移后,原所有者不能再访问数据,就不会出现多个变量同时写同一数据的竞争。
- 借用规则:不可变借用允许多个读取操作同时进行,因为读取不会修改数据,所以不会产生竞争。可变借用同一时间只能有一个,防止了多个写操作或者读写操作同时进行的竞争。例如在多线程场景下,如果一个线程持有可变借用(写权限),其他线程就无法获取借用(无论是可变还是不可变),从而避免了数据竞争。