Следите за новинками
в нашем Telegram канале. Жми, чтобы подписаться:)
1079 of 1246 menu
◀ ▶

Класс Condvar

Класс Condvar (condition variable) представляет собой примитив синхронизации, который позволяет блокировать выполнение одного или нескольких потоков до тех пор, пока другой поток не уведомит их о наступлении определённого события. Условная переменная всегда используется совместно с мьютексом Mutex, который защищает общие данные. Метод new создаёт новую условную переменную, метод wait блокирует текущий поток и освобождает мьютекс, а методы notify_one и notify_all пробуждают один или все ожидающие потоки соответственно.

Синтаксис

use std::sync::{Condvar, Mutex}; let pair = (Mutex::new(value), Condvar::new());

Пример

Давайте создадим условную переменную вместе с мьютексом и посмотрим на базовое ожидание и уведомление:

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 handle = thread::spawn(move || { let (lock, cvar) = &*pair2; let mut started = lock.lock().unwrap(); *started = true; cvar.notify_one(); }); let (lock, cvar) = &*pair; let mut started = lock.lock().unwrap(); while !*started { started = cvar.wait(started).unwrap(); } handle.join().unwrap(); println!("{}", *started); }

Результат выполнения кода:

true

Пример

Давайте используем метод wait_timeout, чтобы поток не ждал уведомления бесконечно:

use std::sync::{Arc, Condvar, Mutex}; use std::time::Duration; fn main() { let pair = Arc::new((Mutex::new(false), Condvar::new())); let (lock, cvar) = &*pair; let started = lock.lock().unwrap(); let (res, timeout) = cvar .wait_timeout(started, Duration::from_millis(100)) .unwrap(); println!("{}", *res); println!("{}", timeout.timed_out()); }

Результат выполнения кода:

false true

Пример

Давайте используем метод notify_all, чтобы разбудить сразу несколько ожидающих потоков:

use std::sync::{Arc, Condvar, Mutex}; use std::thread; fn main() { let pair = Arc::new((Mutex::new(0), Condvar::new())); let mut handles = vec![]; for _ in 0..3 { let pair = Arc::clone(&pair); handles.push(thread::spawn(move || { let (lock, cvar) = &*pair; let mut count = lock.lock().unwrap(); while *count == 0 { count = cvar.wait(count).unwrap(); } *count })); } let (lock, cvar) = &*pair; let mut count = lock.lock().unwrap(); *count = 42; cvar.notify_all(); drop(count); for handle in handles { println!("{}", handle.join().unwrap()); } }

Результат выполнения кода:

42 42 42

Смотрите также

  • метод new,
    который создаёт новую условную переменную
  • метод wait,
    который блокирует поток до получения уведомления
  • метод wait_timeout,
    который блокирует поток на указанное время
  • метод notify_one,
    который пробуждает один ожидающий поток
← →
↑
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить