面试题答案
一键面试场景描述
假设有一个银行账户类 BankAccount
,包含账户余额字段。多个线程可能同时对该账户进行存款和取款操作,如果没有同步机制,就可能出现数据竞争。例如,线程A读取当前余额为100,线程B也读取余额为100,然后线程A存款50,余额变为150,线程B取款30,它认为当前余额还是100,所以取完后余额变为70,但正确结果应该是120。
解决方法
使用 Mutex
和 Arc
来解决这个问题。Arc
(原子引用计数)用于在多个线程间共享数据,Mutex
(互斥锁)用于保证同一时间只有一个线程能访问共享数据。
以下是示例代码:
use std::sync::{Arc, Mutex};
use std::thread;
// 定义银行账户结构体
struct BankAccount {
balance: i32,
}
impl BankAccount {
fn new(initial_balance: i32) -> Self {
BankAccount {
balance: initial_balance,
}
}
fn deposit(&mut self, amount: i32) {
self.balance += amount;
}
fn withdraw(&mut self, amount: i32) -> bool {
if self.balance >= amount {
self.balance -= amount;
true
} else {
false
}
}
}
fn main() {
// 使用Arc和Mutex来共享银行账户
let account = Arc::new(Mutex::new(BankAccount::new(100)));
let handles = (0..10).map(|_| {
let account_clone = account.clone();
thread::spawn(move || {
let mut account = account_clone.lock().unwrap();
account.deposit(10);
account.withdraw(5);
})
}).collect::<Vec<_>>();
for handle in handles {
handle.join().unwrap();
}
let final_balance = account.lock().unwrap().balance;
println!("Final balance: {}", final_balance);
}
在上述代码中:
Arc<Mutex<BankAccount>>
确保BankAccount
实例可以在多个线程间安全共享,并且同一时间只有一个线程能获取Mutex
的锁从而访问BankAccount
。account_clone.lock().unwrap()
获取锁,如果获取成功则返回一个智能指针,通过它可以安全地访问和修改BankAccount
的数据。这样就避免了数据竞争问题。