面试题答案
一键面试资源竞争问题产生的原因
在Rust的并发编程中,当多个线程同时访问和修改共享资源(如控制台输出)时,就会出现资源竞争问题。因为线程调度是由操作系统控制的,不同线程对共享资源的操作顺序是不确定的。例如,线程A可能在输出一部分内容后,被线程B抢占CPU,线程B也开始输出,从而导致输出结果混乱。
解决资源竞争问题采用的机制
- Mutex(互斥锁):Mutex提供了一种机制,在任何时刻只允许一个线程访问共享资源。线程必须先获取锁,才能访问资源,访问完成后释放锁,其他线程才能获取锁进行访问。
- RwLock(读写锁):适用于读多写少的场景。允许多个线程同时进行读操作,但只允许一个线程进行写操作。写操作时会独占锁,防止其他读写操作。在控制台读写场景中,由于写操作较多,Mutex更合适。
代码示例
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let shared_data = Arc::new(Mutex::new(String::new()));
let mut handles = vec![];
for _ in 0..2 {
let data = Arc::clone(&shared_data);
let handle = thread::spawn(move || {
let mut data = data.lock().unwrap();
data.push_str("Hello from a thread!\n");
println!("{}", data);
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
}
在这个示例中:
Arc<Mutex<String>>
用于创建一个线程安全的可共享的字符串。Arc
是原子引用计数类型,用于在多个线程间共享数据,Mutex
用于保证同一时间只有一个线程能访问这个字符串。- 在每个线程中,先通过
lock()
方法获取锁,这个操作会阻塞线程直到获取到锁。unwrap()
用于在获取锁失败(理论上不太可能,除非锁被 poisoned)时使程序崩溃。 - 获取锁后,对字符串进行操作并输出,操作完成后,锁会自动释放(当
data
离开作用域时),其他线程就可以获取锁进行操作。