面试题答案
一键面试- 是否会导致死锁:
- 这段代码会导致死锁。
- 原因是
handle1
线程首先获取data1
的锁,然后尝试获取data2
的锁;而handle2
线程首先获取data2
的锁,然后尝试获取data1
的锁。如果handle1
获取了data1
的锁,同时handle2
获取了data2
的锁,那么两个线程都会阻塞等待对方释放锁,从而形成死锁。
- 避免死锁的方法:
- 方法一:固定锁获取顺序:
- 确保所有线程以相同的顺序获取锁。例如,两个线程都先获取
data1
的锁,再获取data2
的锁。
use std::sync::{Arc, Mutex}; use std::thread; let data1 = Arc::new(Mutex::new(0)); let data2 = Arc::new(Mutex::new(1)); let handle1 = thread::spawn(move || { let lock1 = data1.lock().unwrap(); let lock2 = data2.lock().unwrap(); // 进行一些操作 }); let handle2 = thread::spawn(move || { let lock1 = data1.lock().unwrap(); let lock2 = data2.lock().unwrap(); // 进行一些操作 }); handle1.join().unwrap(); handle2.join().unwrap();
- 确保所有线程以相同的顺序获取锁。例如,两个线程都先获取
- 方法二:使用
try_lock
:- 使用
try_lock
方法尝试获取锁,如果获取失败则释放已获取的锁并进行重试或采取其他策略。
use std::sync::{Arc, Mutex}; use std::thread; let data1 = Arc::new(Mutex::new(0)); let data2 = Arc::new(Mutex::new(1)); let handle1 = thread::spawn(move || { loop { let lock1 = match data1.try_lock() { Ok(lock) => lock, Err(_) => { std::thread::yield_now(); continue; } }; let lock2 = match data2.try_lock() { Ok(lock) => lock, Err(_) => { drop(lock1); std::thread::yield_now(); continue; } }; // 进行一些操作 break; } }); let handle2 = thread::spawn(move || { loop { let lock1 = match data1.try_lock() { Ok(lock) => lock, Err(_) => { std::thread::yield_now(); continue; } }; let lock2 = match data2.try_lock() { Ok(lock) => lock, Err(_) => { drop(lock1); std::thread::yield_now(); continue; } }; // 进行一些操作 break; } }); handle1.join().unwrap(); handle2.join().unwrap();
- 使用
- 方法一:固定锁获取顺序: