Create Dead-lock with Rust Mutex

이택영·2024년 5월 7일
post-thumbnail

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());
}
profile
괴발개발

0개의 댓글