std::sync::Condvar

基本使用

cvar.notify_one();通知单个任务
cvar.wait(guard).unwrap();获取通知

发送

notify_one

只叫醒1个正在等待的线程

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

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

    let t1 = thread::spawn(move || {
        thread::sleep(std::time::Duration::from_secs(5));
        let (lock, cvar) = &*pair2;
        let mut guard = lock.lock().unwrap();
        *guard = true;
        // 通知cvar
        cvar.notify_one();
    });

    let t2 = thread::spawn(move || {
        let (lock, cvar) = &*pair;
        let mut guard = lock.lock().unwrap();
        // 检查条件
        while !*guard {
            println!("waiting...: {}", *guard);
            // 等待通知, 释放锁
            guard = cvar.wait(guard).unwrap();
        }
        print!("done")
    });

    t1.join().unwrap();
    t2.join().unwrap();
}
waiting...: false
done%

多线程使用notify_one

随机挑一个线程唤醒(操作系统决定)

不建议这样写

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

fn main() {
    let pair = Arc::new((Mutex::new(false), Condvar::new()));
    let mut v = Vec::new();
    for i in 0..4 {
        let pair_clone = Arc::clone(&pair);
        let t1 = thread::spawn(move || {
            println!("等待[{}]", i);
            let (lock, cvar) = &*pair_clone;
            let mut guard = lock.lock().unwrap();
            let (new_guard, timeout_result) =
                cvar.wait_timeout(guard, Duration::from_secs(5)).unwrap();

            if timeout_result.timed_out() {
                println!("等待超时[{}]", i)
            } else {
                println!("done[{}]", i)
            }
        });
        v.push(t1);
    }

    let t2 = thread::spawn(move || {
        thread::sleep(Duration::from_secs(2));
        let (lock, cvar) = &*pair;
        let mut guard = lock.lock().unwrap();
        *guard = true;
        cvar.notify_one();
    });
    t2.join().unwrap();
    for vv in v {
        vv.join().unwrap();
    }
}
等待[3]
等待[2]
等待[1]
等待[0]
done[3]
等待超时[2]
等待超时[1]
等待超时[0]

notify_all

叫醒所有正在等待的线程

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

fn main() {
    let pair = Arc::new((Mutex::new(false), Condvar::new()));
    let mut v = Vec::new();
    // 多线程监听
    for i in 0..4 {
        let pair_clone = Arc::clone(&pair);
        let t1 = thread::spawn(move || {
            let (lock, cvar) = &*pair_clone;
            let mut guard = lock.lock().unwrap();
            // 检查条件Mutex内容
            while !*guard {
                println!("waiting[{}]...: {}", i, *guard);
                // 1.等待通知, 释放Mutex锁
                // 2.收到通知, 重新获取Mutex内容
                guard = cvar.wait(guard).unwrap();
            }
            // 3.跳出循环todo
            println!("done[{}]", i)
        });
        v.push(t1);
    }

    let t2 = thread::spawn(move || {
        thread::sleep(Duration::from_secs(2));
        let (lock, cvar) = &*pair;
        let mut guard = lock.lock().unwrap();
        *guard = true;
        cvar.notify_all();
    });
    t2.join().unwrap();
    for vv in v {
        vv.join().unwrap();
    }
}
waiting[0]...: false
waiting[2]...: false
waiting[1]...: false
waiting[3]...: false
done[1]
done[2]
done[3]
done[0]

等待

wait

无限期等待直到被通知

  • wait(guard)返回MutexGuard<T>
use std::time::Duration;
use std::sync::{Arc, Condvar, Mutex};
use std::thread;

fn main() {
    let pair = Arc::new((Mutex::new(false), Condvar::new()));
    let pair1 = Arc::clone(&pair);

    let t1 = thread::spawn(move || {
        let (lock, cvar) = &*pair;
        let mut guard = lock.lock().unwrap();
        // 检查条件Mutex内容
        while !*guard {
            println!("waiting...: {}", *guard);
            // 1.等待通知, 释放Mutex锁
            // 2.收到通知, 重新获取Mutex内容
            guard = cvar.wait(guard).unwrap();
        }
        // 3.跳出循环todo
        print!("done")
    });

    let t2 = thread::spawn(move || {
        thread::sleep(Duration::from_secs(2));
        let (lock, cvar) = &*pair1;
        let mut guard = lock.lock().unwrap();
        *guard = true;
        cvar.notify_one();
    });

    t1.join().unwrap();
    t2.join().unwrap();
}
waiting...: false
done%

wait_timeout

带超时时间的等待

  • wait_timeout(guard, timeout)返回(MutexGuard<T>, WaitTimeoutResult)
use std::time::Duration;
use std::sync::{Arc, Condvar, Mutex};
use std::thread;

fn main() {
    let pair = Arc::new((Mutex::new(false), Condvar::new()));
    let pair1 = Arc::clone(&pair);

    let t1 = thread::spawn(move || {
        let (lock, cvar) = &*pair;
        let guard = lock.lock().unwrap();
        // new_guard是MutexGuard
        // timeout_result是WaitTimeoutResult
        let (new_guard, timeout_result) = cvar.wait_timeout(guard, Duration::from_secs(1)).unwrap();
        println!("new_guard: {}", *new_guard);
        println!("timeout_result: {:?}", timeout_result);
        println!("time_out: {}", timeout_result.timed_out());
    });

    let t2 = thread::spawn(move || {
        thread::sleep(Duration::from_secs(2));
        let (lock, cvar) = &*pair1;
        let mut guard = lock.lock().unwrap();
        *guard = true;
        cvar.notify_one();
    });

    t1.join().unwrap();
    t2.join().unwrap();
}
new_guard: false
timeout_result: WaitTimeoutResult(true)
time_out: true

wait_while

带条件的无限等待

  • wait_while(guard, condition)返回MutexGuard<T>
use std::time::{Duration, Instant, SystemTime};
use std::sync::{Arc, Condvar, Mutex};
use std::thread;

fn main() {
    let pair = Arc::new((Mutex::new(0), Condvar::new()));
    let pair1 = Arc::clone(&pair);

    let t1 = thread::spawn(move || {
        let (lock, cvar) = &*pair;
        let guard = lock.lock().unwrap();
        // new_guard是MutexGuard
        // pending是MutexGuard(guard)内部的值
        let new_guard = cvar.wait_while(guard, |pending| {
            println!("pending: {}", pending);
            // 内部返回false时才结束等待
            // 返回true时,会一直等待
            *pending < 1
        }).unwrap();
        println!("new_guard: {}", *new_guard);
    });

    let t2 = thread::spawn(move || {
        thread::sleep(Duration::from_secs(1));
        let (lock, cvar) = &*pair1;
        let mut guard = lock.lock().unwrap();
        *guard += 1;
        cvar.notify_one();
    });

    t1.join().unwrap();
    t2.join().unwrap();
}
pending: 0
pending: 1
new_guard: 1

wait_timeout_while

带条件和超时的等待
打印两次pending原因,第一次获取到锁打印判断,第二次是因为超时,获取到锁打印判断

  • wait_timeout_while(guard, timeout, condition)返回(MutexGuard<T>, WaitTimeoutResult)
use std::time::{Duration, Instant, SystemTime};
use std::sync::{Arc, Condvar, Mutex};
use std::thread;

fn main() {
    let pair = Arc::new((Mutex::new(0), Condvar::new()));
    let pair1 = Arc::clone(&pair);

    let t1 = thread::spawn(move || {
        let (lock, cvar) = &*pair;
        let guard = lock.lock().unwrap();
        // new_guard是MutexGuard
        // timeout_result是WaitTimeoutResult
        // pending是MutexGuard(guard)内部的值
        let (new_guard, timeout_result) = cvar.wait_timeout_while(guard, Duration::from_secs(1), |pending| {
            println!("pending[t1]: {}", pending);
            // 内部返回false时才结束等待
            // 返回true时,会一直等待
            *pending < 1
        }).unwrap();
        println!("new_guard[t1]: {}", *new_guard);
        println!("timeout_result: {}", timeout_result.timed_out());
    });

    let t2 = thread::spawn(move || {
        thread::sleep(Duration::from_secs(10));
        let (lock, cvar) = &*pair1;
        let mut guard = lock.lock().unwrap();
        *guard += 1;
        cvar.notify_one();
    });

    t1.join().unwrap();
    t2.join().unwrap();
}
pending[t1]: 0
pending[t1]: 0
new_guard[t1]: 0
timeout_result: true

错误

WaitTimeoutResult

  • WaitTimeoutResult.timed_out(): 返回是否超时bool
posted @ 2026-04-15 21:26  lxd670  阅读(15)  评论(0)    收藏  举报