在Rust中的多个线程中读取和写入同一变量

p4rjhz4m  于 2022-11-12  发布在  其他
关注(0)|答案(1)|浏览(165)

我正在做一个简单的程序来模拟一个超市队列来学习Rust。这个程序由两个线程组成。一个是向超市队列中添加人(字符'x'),另一个是删除他们。
我使用Arc和Mutex来处理并发性,但似乎第一个线程从未释放var,因此第二个线程不起作用。
代码如下:

let queue = Arc::new(Mutex::new(Vec::<char>::new()));

let queue1 = Arc::clone(&queue);
    thread::spawn(move || loop {
        let mut aux = queue1.lock().unwrap();
        aux.push('x');
        print_queue(&aux);
        thread::sleep(Duration::from_secs(3));
    });

thread::spawn(move || loop {
        let mut aux = queue.lock().unwrap();
        println!("AUX state: {:?}", aux);
        if !&aux.is_empty() {
            aux.pop();
        }
        print_queue(&aux);
        let mut rng = rand::thread_rng();
        thread::sleep(Duration::from_secs(rng.gen_range(1..10)));
    });

AUX状态的打印永远不会显示。我做错了什么?

jv4diomz

jv4diomz1#

您的代码使用的是以下模式:

loop {
    let mut guard = mutex.lock().unwrap();
    // do something with `guard`

    thread::sleep(duration);

    // `guard` is implicitly dropped at the end of the scope
}

这段代码的问题在于互斥体保护(在本例中为guard)持有锁,并一直持有到它被删除为止,在本例中,当变量超出作用域时就会发生这种情况。但它在线程休眠 * 之后 * 才超出作用域,因此线程在休眠时仍然持有锁。
为了避免这种情况,您应该在线程休眠之前,在使用完保护之后立即删除它:

loop {
    {
        let mut guard = mutex.lock().unwrap();
        // do something with `guard`

        // implicitly drop `guard` at the end of the inner scope, before sleep
    }
    thread::sleep(duration);
}

loop {
    let mut guard = mutex.lock().unwrap();
    // do something with `guard`

    // explicitly drop `guard` before sleep
    drop(guard);

    thread::sleep(duration);
}

相关问题