Skip to content

Instantly share code, notes, and snippets.

@gmelodie
Last active February 16, 2024 22:28
Show Gist options
  • Save gmelodie/c6cb0a13d71d874af5a2674209917e3a to your computer and use it in GitHub Desktop.
Save gmelodie/c6cb0a13d71d874af5a2674209917e3a to your computer and use it in GitHub Desktop.
Rust deadlock example with multiple threads
// help from https://gist.github.com/wuct/b98f42dba91a8c08cc6ba2d820d94c1c
//
use std::sync::{Arc, Mutex};
use std::thread;
fn acquire_lock(a: Arc<Mutex<i32>>, b: Arc<Mutex<i32>>) {
// note: if you do the commented out it doesn't deadlock, think about why that is
// let mut a_num = *a.lock().unwrap();
// a_num += 1;
let mut a_num = a.lock().unwrap();
*a_num += 1;
let delay = std::time::Duration::from_millis(1000);
std::thread::sleep(delay);
// let mut b_num = *b.lock().unwrap();
// b_num += 1;
let mut b_num = b.lock().unwrap();
*b_num += 1;
println!("{a_num} {b_num}");
}
fn main() {
let mux1: Arc<Mutex<i32>> = Arc::new(Mutex::new(0));
let mux2: Arc<Mutex<i32>> = Arc::new(Mutex::new(0));
let mux1_clone1 = Arc::clone(&mux1);
let mux2_clone1 = Arc::clone(&mux2);
let mux1_clone2 = Arc::clone(&mux1);
let mux2_clone2 = Arc::clone(&mux2);
let t1 = thread::spawn(move || acquire_lock(mux1_clone1, mux2_clone1));
let t2 = thread::spawn(move || acquire_lock(mux2_clone2, mux1_clone2));
let _ = t1.join();
let _ = t2.join();
println!("Done {}", *mux1.lock().unwrap()); // never reach here
println!("Done {}", *mux2.lock().unwrap()); // never reach here
println!("the end?");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment