kubo39's blog

ただの雑記です。

Rustのlockとスコープのはなし

こういうコードを書くと当然deadlockする。

use std::sync::{Mutex, Arc};
use std::thread;

fn main() {
    let mut lock = Arc::new(Mutex::new(false));
    let mut cloned_lock = lock.clone();

    let th = thread::spawn(move|| {
        loop {
            let mut quit = cloned_lock.lock().unwrap();
            if *quit {
                break;
            }
        }
    });

    let mut quit = lock.lock().unwrap();
    *quit = true;
    th.join();
}

ロックの開放タイミングをいいかんじにするとちゃんと終了する。

use std::sync::{Mutex, Arc};
use std::thread;

fn main() {
    let mut lock = Arc::new(Mutex::new(false));
    let mut cloned_lock = lock.clone();

    let th = thread::spawn(move|| {
        loop {
            let mut quit = cloned_lock.lock().unwrap();
            if *quit {
                break;
            }
        }
    });

    {
        let mut quit = lock.lock().unwrap();
        *quit = true;
    }
    th.join();
}

さらに以下のように書いても正常に終了する。 おそらく変数スコープのところで獲得・開放してくれているのだろう。

use std::sync::{Mutex, Arc};
use std::thread;

fn main() {
    let mut lock = Arc::new(Mutex::new(false));
    let mut cloned_lock = lock.clone();

    let th = thread::spawn(move|| {
        loop {
            let mut quit = cloned_lock.lock().unwrap();
            if *quit {
                break;
            }
        }
    });

    *lock.lock().unwrap() = true;
    th.join();
}

Rustいいなあ。