面试题答案
一键面试- 采取的措施:
- 使用
std::sync::Mutex
或std::sync::RwLock
来保护共享数据。Mutex
提供互斥访问,一次只有一个线程可以获取锁并访问共享数据,从而避免数据竞争。RwLock
允许多个线程同时进行读操作,但写操作时会独占锁,也能防止数据竞争。 - 结合
Arc
(原子引用计数)来在多个线程间共享数据。Arc
用于在堆上分配数据,并允许多个线程持有对该数据的引用。
- 使用
- 原理解释:
- 所有权:Rust的所有权系统确保每个值都有一个唯一的所有者。当我们使用
Arc
来共享数据时,Arc
拥有数据的所有权,并且通过引用计数来跟踪有多少个线程持有对数据的引用。当引用计数降为0时,数据被释放。 - 借用:
Mutex
和RwLock
通过借用的方式来访问共享数据。当一个线程获取Mutex
的锁时,它实际上是借用了Mutex
内部的数据。因为Mutex
一次只允许一个线程获取锁,所以不会出现多个线程同时可变借用(写操作)或同时存在可变借用和不可变借用(读写冲突)的情况,这符合Rust借用规则,从而避免数据竞争。 - 生命周期:
Arc
和Mutex
所管理的数据的生命周期由Arc
的引用计数决定。只要有Arc
实例持有数据的引用,数据就会一直存活。
- 所有权:Rust的所有权系统确保每个值都有一个唯一的所有者。当我们使用
- 示例代码:
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let shared_data = Arc::new(Mutex::new(Vec::new()));
let mut handles = Vec::new();
for _ in 0..10 {
let data = Arc::clone(&shared_data);
let handle = thread::spawn(move || {
let mut numbers = data.lock().unwrap();
numbers.push(1);
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
let result = shared_data.lock().unwrap();
println!("Final result: {:?}", result);
}
在这个示例中,Arc<Mutex<Vec<i32>>>
用于在多个线程间共享 Vec<i32>
。每个线程通过获取 Mutex
的锁来可变借用 Vec<i32>
并向其添加数据,从而确保了线程安全。