面试题答案
一键面试对并发程序正确性的影响
- 死锁风险增加:当一个线程获取了锁并发生了panic,该锁可能会进入中毒状态。其他等待该锁的线程会永远阻塞,导致死锁。例如,假设有两个线程A和B,共享一个互斥锁
Mutex
保护的数据。线程A获取锁后进行一些操作,期间发生panic,锁中毒。线程B尝试获取该锁,由于锁中毒,B将永远等待,导致程序无法继续执行。
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let data = Arc::new(Mutex::new(0));
let data_clone = data.clone();
let thread1 = thread::spawn(move || {
let mut guard = data_clone.lock().unwrap();
// 模拟一些可能发生panic的操作
panic!("Something went wrong");
*guard += 1;
});
let thread2 = thread::spawn(move || {
let mut guard = data.lock().unwrap();
*guard += 1;
});
thread1.join().unwrap();
thread2.join().unwrap();
}
在上述代码中,线程1获取锁后panic,锁中毒,线程2获取锁时会阻塞。
- 数据不一致:如果一个线程在持有锁时panic,其他线程可能无法再安全地访问受保护的数据。例如,假设一个银行转账操作,从账户A向账户B转账,在获取锁修改账户A余额后,还未修改账户B余额时发生panic,锁中毒,其他线程可能无法正确处理后续转账操作,导致数据不一致。
对并发程序性能的影响
- 线程阻塞浪费资源:等待中毒锁的线程处于阻塞状态,占用系统资源但不执行有用的工作。这些线程无法参与其他任务,降低了整个系统的并发性能。例如在一个多线程的Web服务器中,如果处理请求的线程因为等待中毒锁而阻塞,会导致其他请求得不到及时处理,降低服务器的吞吐量。
对并发程序资源管理的影响
- 资源泄漏:如果锁保护的资源在锁中毒时没有正确释放,可能导致资源泄漏。例如,锁保护一个文件描述符,持有锁的线程panic后,文件描述符可能没有被正确关闭,导致文件资源一直被占用,直到程序结束。
use std::sync::{Arc, Mutex};
use std::fs::File;
use std::thread;
fn main() {
let file = Arc::new(Mutex::new(File::create("test.txt").unwrap()));
let file_clone = file.clone();
let thread1 = thread::spawn(move || {
let mut guard = file_clone.lock().unwrap();
// 模拟一些可能发生panic的操作
panic!("Something went wrong");
// 这里文件描述符没有机会正确关闭
});
let thread2 = thread::spawn(move || {
let mut guard = file.lock().unwrap();
// 由于锁中毒,线程2可能无法获取锁来关闭文件
});
thread1.join().unwrap();
thread2.join().unwrap();
}
在上述代码中,线程1获取锁后panic,文件资源可能无法正确释放。