Showed an example, that raceconditions are still possible even with mutex
parent
9e36ee2d01
commit
b67f32704e
|
|
@ -0,0 +1,58 @@
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use std::thread;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// A shared bank account starting with $100
|
||||||
|
let account_balance = Arc::new(Mutex::new(100));
|
||||||
|
|
||||||
|
// Thread A: Attempts to withdraw $80
|
||||||
|
let balance_clone1 = Arc::clone(&account_balance);
|
||||||
|
let handle1 = thread::spawn(move || {
|
||||||
|
// 1. CHECK: Lock the account just to check the balance
|
||||||
|
let current_balance = *balance_clone1.lock().unwrap();
|
||||||
|
|
||||||
|
if current_balance >= 80 {
|
||||||
|
println!("Thread A: Balance is ${}. Approval granted!", current_balance);
|
||||||
|
|
||||||
|
// Simulate a tiny delay (e.g., network latency or CPU context switch)
|
||||||
|
// This gives Thread B time to sneak in and check the balance
|
||||||
|
thread::sleep(Duration::from_millis(5));
|
||||||
|
|
||||||
|
// 2. ACT: Lock again to deduct the money
|
||||||
|
let mut balance_guard = balance_clone1.lock().unwrap();
|
||||||
|
*balance_guard -= 80;
|
||||||
|
println!("Thread A: Successfully withdrew $80.");
|
||||||
|
} else {
|
||||||
|
println!("Thread A: Declined. Insufficient funds.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Thread B: Simultaneously attempts to withdraw $80
|
||||||
|
let balance_clone2 = Arc::clone(&account_balance);
|
||||||
|
let handle2 = thread::spawn(move || {
|
||||||
|
// 1. CHECK: Lock the account just to check the balance
|
||||||
|
let current_balance = *balance_clone2.lock().unwrap();
|
||||||
|
|
||||||
|
if current_balance >= 80 {
|
||||||
|
println!("Thread B: Balance is ${}. Approval granted!", current_balance);
|
||||||
|
|
||||||
|
// Simulate a tiny delay (e.g., network latency or CPU context switch)
|
||||||
|
// This gives Thread B time to sneak in and check the balance
|
||||||
|
thread::sleep(Duration::from_millis(5));
|
||||||
|
|
||||||
|
// 2. ACT: Lock again to deduct the money
|
||||||
|
let mut balance_guard = balance_clone2.lock().unwrap();
|
||||||
|
*balance_guard -= 80;
|
||||||
|
println!("Thread B: Successfully withdrew $80.");
|
||||||
|
} else {
|
||||||
|
println!("Thread B: Declined. Insufficient funds.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
handle1.join().unwrap();
|
||||||
|
handle2.join().unwrap();
|
||||||
|
|
||||||
|
// Final result
|
||||||
|
println!("Final Bank Balance: ${}", *account_balance.lock().unwrap());
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue