47 lines
1.8 KiB
Rust
47 lines
1.8 KiB
Rust
use std::sync::{Arc, Mutex};
|
|
use std::thread;
|
|
use std::time::Duration;
|
|
|
|
fn main() {
|
|
// 1. Create two separate resources, each protected by its own Mutex
|
|
let resource_a = Arc::new(Mutex::new("Resource A Data"));
|
|
let resource_b = Arc::new(Mutex::new("Resource B Data"));
|
|
|
|
// 2. Thread 1: Tries to lock A first, then B
|
|
let a_clone1 = Arc::clone(&resource_a);
|
|
let b_clone1 = Arc::clone(&resource_b);
|
|
let handle1 = thread::spawn(move || {
|
|
// Grab Lock A
|
|
let _guard_a = a_clone1.lock().unwrap();
|
|
println!("Thread 1: Successfully locked Resource A!");
|
|
|
|
// Sleep for a moment to guarantee Thread 2 has time to lock Resource B
|
|
thread::sleep(Duration::from_millis(10));
|
|
|
|
println!("Thread 1: Trying to lock Resource B... (Waiting)");
|
|
let _guard_b = b_clone1.lock().unwrap(); // Stalled forever here
|
|
println!("Thread 1: Successfully locked Resource B!");
|
|
});
|
|
|
|
// 3. Thread 2: Tries to lock B first, then A (The opposing order causes the deadlock!)
|
|
let a_clone2 = Arc::clone(&resource_a);
|
|
let b_clone2 = Arc::clone(&resource_b);
|
|
let handle2 = thread::spawn(move || {
|
|
// Grab Lock B
|
|
let _guard_b = b_clone2.lock().unwrap();
|
|
println!("Thread 2: Successfully locked Resource B!");
|
|
|
|
// Sleep for a moment to guarantee Thread 1 has time to lock Resource A
|
|
thread::sleep(Duration::from_millis(10));
|
|
|
|
println!("Thread 2: Trying to lock Resource A... (Waiting)");
|
|
let _guard_a = a_clone2.lock().unwrap(); // Stalled forever here
|
|
println!("Thread 2: Successfully locked Resource A!");
|
|
});
|
|
|
|
// 4. Wait for both threads (Spoiler: They will never finish)
|
|
handle1.join().unwrap();
|
|
handle2.join().unwrap();
|
|
|
|
println!("Program finished successfully!"); // This line will never execute
|
|
} |