Course contentsShow
← Rust
Lesson 1100 of 1,91010. Concurrency PrimitivesFree lesson

Condition Variables for State Changes

You will implement efficient waiting patterns where threads sleep until a specific application state occurs.

In this lesson, you will learn how to use std::sync::Condvar to make your threads sleep efficiently while waiting for a specific condition to become true, avoiding the performance drain of "busy-waiting."

The Problem with Busy-Waiting

When you need a thread to wait for a shared state to change (like a data buffer filling up), the naive approach is to loop and check a Mutex repeatedly. This is called busy-waiting. It consumes 100% of a CPU core just to ask "is it ready yet?" over and over.

The Solution: Condition Variables

A condition variable allows a thread to suspend execution (go to sleep) and relinquish its CPU time. It only wakes up when another thread signals that the state has changed.

To use a Condvar effectively, you must pair it with a Mutex. The condition variable relies on the mutex to protect the state, and it provides a mechanism to atomically release the lock while going to sleep.

Example: Waiting for a Signal

Imagine a worker thread waiting for a "ready" flag:

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

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

thread::spawn(move || {
    let (lock, cvar) = &*pair_clone;
    // Perform some work...
    let mut ready = lock.lock().unwrap();
    *ready = true;
    cvar.notify_one(); // Wake up the waiting thread
});

// Main thread waits for the condition
let (lock, cvar) = &*pair;
let mut ready = lock.lock().unwrap();
while !*ready {
    // wait() unlocks the mutex and blocks the thread
    // When notified, it re-acquires the lock
    ready = cvar.wait(ready).unwrap();
}
println!("State changed: ready is true!");

Why the while Loop?

You might notice the while !*ready loop. This is critical. Due to "spurious wakeups"—where a thread might wake up even without a notification—you must always re-verify the condition after waking up. The wait method automatically re-acquires the mutex lock before it returns, ensuring that when you exit the loop, you safely own the protected state again.

Key Takeaway: Use a Condvar paired with a Mutex to block threads until a specific state is reached, ensuring your program remains responsive without wasting CPU cycles on busy-waiting loops.