Rust-Book: Shared-State Concurrency
Create Dead-lock and some ways to solve this Dead-lock.
| If you remove sleep function at middle of thread
| Dead-lock might not happen.
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
// to produce Dead-lock
// thread X: -- lock(A) ------ lock(B) ----- free(A) - free(B)
// --------|AO------------|BX----------A.--------B.-------
// ------------|BO------------|AX-----------B.--------A.-------
// thread Y: ------ lock(B) ------ lock(A) ------ free(B) - free(A)
//
// Dead-lock created
// when '|' means try to get lock of object and '|O' means success to get lock
// and '|X' means failed to get lock (waiting forever)
//
//
// to prevent this situatoin set order of get locks like domino
// at every thread
// if get one lock then guaranteed to get other locks
// so set exact order of get locks
//
// thread X: -- lock(A) ------ lock(B) ----- free(A) - free(B)
// --------|AO------------|BO----------A.--------B.-------
// ---------------------------------------|AO------------|AO-----------A.--------B.-------
// thread Y: --------------------------------- lock(A) ------ lock(B) ------ free(A) - free(B)
//
//
// or just get one lock at a time is another way to prevent Dead-lock
//
// thread X: -- lock(A) ------ free(A) ------ lock(B) ----- free(B) ------
// --------|AO-----------A.--------------|BO----------B.-------
// ------------|BO-----------B.-------------B.--------A.-------
// thread Y: ------ lock(B) ------ free(B) ------ lock(B) - free(A)
//
fn main() {
let counter1 = Arc::new(Mutex::new(0));
let counter2 = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..10 {
let counter1 = Arc::clone(&counter1);
let counter2 = Arc::clone(&counter2);
let handle = thread::spawn(move || {
let mut num1 = counter1.lock().unwrap();
*num1 += 1;
println!("even num1: {}", num1);
// drop(num1);
thread::sleep(Duration::from_millis(10));
let mut num2 = counter2.lock().unwrap();
*num2 += 1;
println!("even num2: {}", num2);
// drop(num2);
thread::sleep(Duration::from_millis(10));
});
handles.push(handle);
}
for _ in 0..10 {
let counter2 = Arc::clone(&counter2);
let counter1 = Arc::clone(&counter1);
let handle = thread::spawn(move || {
let mut num2 = counter2.lock().unwrap();
*num2 += 1;
println!("odd num2: {}", num2);
// drop(num2);
thread::sleep(Duration::from_millis(10));
let mut num1 = counter1.lock().unwrap();
*num1 += 1;
println!("odd num1: {}", num1);
// drop(num1);
thread::sleep(Duration::from_millis(10));
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("Result: {}", *counter1.lock().unwrap());
}