条件变量与thread :: sleep不兼容

时间:2017-02-20 20:07:49

标签: multithreading rust mutex

我不确定我是否了解Rust Mutex es和条件变量的并发支持。在下面的代码中,main线程将poll_thread设置为空闲两秒钟,然后设置为"读取寄存器"持续2秒,然后返回"空闲":

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

#[derive(PartialEq, Debug)]
enum Command {
    Idle,
    ReadRegister(u32),
}

fn poll_thread(sync_pair: Arc<(Mutex<Command>, Condvar)>) {
    let &(ref mutex, ref cvar) = &*sync_pair;

    loop {
        let mut flag = mutex.lock().unwrap();
        while *flag == Command::Idle {
            flag = cvar.wait(flag).unwrap();
        }

        match *flag {
            Command::Idle => {
                println!("WHAT IMPOSSIBLE!");
                panic!();
            }
            Command::ReadRegister(i) => {
                println!("You want me to read {}?", i);
                thread::sleep(time::Duration::from_millis(450));
                println!("Ok, here it is: {}", 42);
            }
        }
    }
}

pub fn main() {
    let pair = Arc::new((Mutex::new(Command::Idle), Condvar::new()));
    let pclone = pair.clone();
    let rx_thread = thread::spawn(|| poll_thread(pclone));

    let &(ref mutex, ref cvar) = &*pair;

    for i in 0..10 {
        thread::sleep(time::Duration::from_millis(500));
        if i == 4 {
            println!("Setting ReadRegister");
            let mut flag = mutex.lock().unwrap();
            *flag = Command::ReadRegister(5);
            println!("flag is = {:?}", *flag);
            cvar.notify_one();
        } else if i == 8 {
            println!("Setting Idle");
            let mut flag = mutex.lock().unwrap();
            *flag = Command::Idle;
            println!("flag is = {:?}", *flag);
            cvar.notify_one();
        }
    }
    println!("after notify_one()");

    rx_thread.join();
}

这可以按预期工作,但是当取消注释450毫秒的睡眠线时,代码通常会保留在&#34; read&#34;状态而不是返回等待条件变量cvar.wait()。有时它会在15秒后恢复闲置!

我认为当poll_thread到达loop的底部时,它会释放锁定,允许main获取并设置flag = Command::Idle,大约一半第二个,poll_thread将返回空闲状态,但似乎poll_thread睡眠时不会发生这种情况。为什么呢?

0 个答案:

没有答案