Open3

Mutex

katayama8000katayama8000
  • mutexとは
  • サンプルコード
    let mutex: Mutex<i32> = Mutex::new(0);
    println!("mutex: {:?}", mutex);
    let mut val: std::sync::MutexGuard<'_, i32> = mutex.lock().unwrap();
    println!("mutex: {:?}", mutex);
    *val = 10;
    println!("val: {}", val);
    drop(val);
mutex: Mutex { data: 0, poisoned: false, .. }
mutex: Mutex { data: <locked>, poisoned: false, .. }
val: 10

スコープを抜ける or drop を呼び出すと、ロックを解除できる

katayama8000katayama8000
  • ロックを取ると、mutex は解放されるまで待っている
  • 待たない、サンプルコード
pub fn run() {
    let counter = Arc::new(Mutex::new(0));

    let handle1 = {
        thread::spawn(move || {
            // wait for 3 seconds
            thread::sleep(std::time::Duration::from_secs(3));
            println!("thread1 ends")
        })
    };

    let handle2 = {
        thread::spawn(move || {
            // wait for 1 second
            thread::sleep(std::time::Duration::from_secs(1));
            println!("thread2 ends")
        })
    };

    handle1.join().unwrap();
    handle2.join().unwrap();
    println!("finish all threads");
}
thread2 ends
thread1 ends
finish all threads

このコードでは、スレッドが二つ同時に走って、指定された秒数待ってから終了する
スレッド同士に特に関係はなく、独立して動いています

  • まつサンプルコード
pub fn run() {
    let counter = Arc::new(Mutex::new(0));

    let counter1 = Arc::clone(&counter);
    let handle1 = thread::spawn(move || {
        println!("thread1 started");
        let mut num = counter1.lock().unwrap();
        println!("counter: {:?}", counter1);
        println!("num: {:?}", num);

        // wait for 3 seconds
        thread::sleep(std::time::Duration::from_secs(3));
        *num += 1;
    });

    let counter2 = Arc::clone(&counter);
    let handle2 = thread::spawn(move || {
        println!("thread2 started");
        let mut num = counter2.lock().unwrap();
        println!("counter: {:?}", counter2);
        println!("num: {:?}", num);
        *num += 1;
    });

    handle1.join().unwrap();
    handle2.join().unwrap();

    println!("Result: {}", *counter.lock().unwrap());
}
thread1 started
counter: Mutex { data: <locked>, poisoned: false, .. }
num: 0
thread2 started
--- 3秒後 ---
counter: Mutex { data: <locked>, poisoned: false, .. }
num: 1
Result: 2

thread2 のロックを取得する箇所で、thread1 でロックが解除されるのを待っている

  • 3秒待つ前に解放する
pub fn run() {
    let counter = Arc::new(Mutex::new(0));

    let counter1 = Arc::clone(&counter);
    let handle1 = thread::spawn(move || {
        println!("thread1 started");
        let mut num = counter1.lock().unwrap();
        println!("counter: {:?}", counter1);
        println!("num: {:?}", num);
        *num += 1;
        drop(num);

        // wait for 3 seconds
        thread::sleep(std::time::Duration::from_secs(3));
    });

    let counter2 = Arc::clone(&counter);
    let handle2 = thread::spawn(move || {
        println!("thread2 started");
        let mut num = counter2.lock().unwrap();
        println!("counter: {:?}", counter2);
        println!("num: {:?}", num);
        *num += 1;
    });

    handle1.join().unwrap();
    handle2.join().unwrap();

    println!("Result: {}", *counter.lock().unwrap());
}
thread1 started
counter: Mutex { data: <locked>, poisoned: false, .. }
num: 0
thread2 started
counter: Mutex { data: <locked>, poisoned: false, .. }
num: 1
--- 3秒後 ---
Result: 2
katayama8000katayama8000
  • デッドロック
  • サンプルコード
fn run3() {
    let counter = Mutex::new(0);
    let lock1 = counter.lock().unwrap();
    let lock2 = counter.lock().unwrap();
    println!("lock: {:?}", lock1);
}

lock2 は lock1 がロックしたものを待っているが、ずっと解放されない