为什么这样使用Condvar等待和通知不会死锁?

Ива*_*хин 5 mutex rust conditional-variable

https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html

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

let pair = Arc::new((Mutex::new(false), Condvar::new()));
let pair2 = Arc::clone(&pair);

// Inside of our lock, spawn a new thread, and then wait for it to start.
thread::spawn(move|| {
    let (lock, cvar) = &*pair2;
    let mut started = lock.lock().unwrap(); // #1
    *started = true;
    // We notify the condvar that the value has changed.
    cvar.notify_one();
});

// Wait for the thread to start up.
let (lock, cvar) = &*pair;
let mut started = lock.lock().unwrap(); // #2
while !*started {
    started = cvar.wait(started).unwrap();
}
Run Code Online (Sandbox Code Playgroud)

如果我理解正确的话,生成线程 ( #1) 中的核心可能会在主线程锁定互斥锁 ( #2) 之后运行。但在这种情况下,主线程永远不会解锁它,因为派生线程无法锁定它并更改值,因此循环会永远运行......或者,是因为某些Condvar机制吗?

Joh*_*ica 7

wait的文档说(强调):

pub fn wait<'a, T>(
    &self,
    guard: MutexGuard<'a, T>
) -> LockResult<MutexGuard<'a, T>>
Run Code Online (Sandbox Code Playgroud)

该函数将自动解锁指定的互斥体(由 表示guard)并阻止当前线程。这意味着对互斥锁解锁后逻辑上发生的任何调用notify_one都是notify_all唤醒该线程的候选者。当此函数调用返回时,指定的锁将被重新获取。

当您cvar.wait在循环内调用时,它会解锁互斥体,这允许生成的线程锁定它并设置startedtrue

  • 当然是带外的,但是你的个人资料中的 c++ 评论让我很高兴,如果你至少在 Rush 方式或 Yes 方式上进步,那么我将购买第一个副本。 (2认同)