10
9

More than 1 year has passed since last update.

Rustでの他スレッドの待ち合わせ(条件変数, wait, notify)

Last updated at Posted at 2021-12-22

rustで他スレッドから通知を待ち合わせるにはMutexとCondvar型の条件変数を用います。使い方は一般的な条件変数と同じで、待ち合わせる方のスレッドはMutexのロックを取得したあと条件変数に対してwaitを呼び出します。通知を行う方のスレッドは条件変数に対してnotifyを呼び出します。

実際に条件変数による待ち合わせを行うコードを以下に示します。
ポイントは以下の通り。

  • 条件変数はMutex変数と対で用います。タプルでまとめて管理すると良いかもしれません。
  • 条件変数とMutex変数はスレッドをまたいで共有されるのでArcでくるみ、Arc::clone()で複製を作って使用します。
  • cond.wait(mutex)は内部でmutexのロックを外してnotifyを待ちます。notifyを受けてwaitから復帰する時にはロックを取得した状態で復帰します。
  • wait関数は実装の都合上notifyを受けていないのに復帰することがあります(偽wakeup)。偽wakeupのケースをケアするためにwaitから復帰した直後にmutexの内容を検査します。
use std::sync::Condvar;
use std::sync::Mutex;
use std::sync::Arc;
use std::thread;
use std::time;

fn main() {
    let cond = Arc::new(Condvar::new());  // 条件変数
    let go = Arc::new(Mutex::new(false)); // ミューテックス変数

    // waitスレッド起動
    let cond_c = Arc::clone(&cond);
    let go_c = Arc::clone(&go);
    let t1 = thread::spawn(move || {
        loop {
            // ロック取得
            let mut go = go_c.lock().unwrap();
            while !*go { // 偽wakeupの場合は再度waitする
                // wait: 内部でロックを外しnotifyを待つ
                //       waitから復帰する際にはミューテックスのlockを取得している
                go = cond_c.wait(go).unwrap();
            }
            println!("wakeup!");
            *go = false;
        }
    });

    // notifyスレッド起動
    let cond_p = Arc::clone(&cond);
    let go_p = Arc::clone(&go);
    let t2 = thread::spawn(move || {
        loop {
            thread::sleep(time::Duration::new(0, 1_000_000_000u32));

            println!("notify!");
            // ミューテックスのロック取得
            let mut go = go_p.lock().unwrap();
            *go = true;

            // 条件変数に対してnotify
            cond_p.notify_all();
        }
    });

    t1.join().unwrap(); 
    t2.join().unwrap();
}
  • waitの他にタイムアウトを指定できるwait_timeが存在します。
  • また、偽wakeupのケアをしてくれるwait_whileも存在します。
10
9
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
9