A condition variable is used to wait for something to happen to data protected by a mutex. It typically has three operations

  • wait: Take a locked mutex, atomically unlock the mutex and put the thread to sleep. When the thread awake by notification, immediately lock the mutex again.
  • notify_one: wake up one waiting thread (if any)
  • notify_all: wake up all waiting thread

A limitation of condition variable is that it must be paired with a mutex. In practice, it is fine since mutex is what we used to synchronize data anyway.

Below is an example in Rust 1

use std::sync::Condvar;
 
let queue = Mutex::new(VecDeque::new());
let not_empty = Condvar::new();
thread::scope(|s| {
    s.spawn(|| {
        // wait for item to arrive in queue
        loop {
            let mut q = queue.lock().unwrap();
            let item = loop {
                if let Some(item) = q.pop_front() {
                    break item;
                } else {
                    q = not_empty.wait(q).unwrap();
                }
            };
        drop(q);
        dbg!(item);
        }
    });
 
    for i in 0.. {
        // put an item in queue and notify the other thread
        queue.lock().unwrap().push_back(i);
        not_empty.notify_one();
        thread::sleep(Duration::from_secs(1));
    }
});

Implementations

  • Rust std::sync::Condvar

Footnotes

Footnotes

  1. Chapter 1, Rust Atomics and Locks by Mara Bos (O’Reilly). Copyright 2023 Mara Bos, 978-1-098-11944-7.