Fundamentos

Variables de condición

Muchos hilos de planta necesitan esperar hasta que algo ocurra: que llegue una pieza, que el depósito alcance el nivel, que se reciba la consigna por el canal. Consultar en bucle (while (!sensor());) desperdicia CPU. La variable de condición permite dormir al hilo hasta que otro le avise.

La espera activa y su coste

En los primeros ejercicios del cuaderno verás esperas por consulta:

while (!sensorEntrada());   // consulta el sensor miles de veces por segundo
cintaEntrada(0);

El hilo está «esperando», pero consume el 100 % de su núcleo. En un microcontrolador además impide dormir la CPU. La alternativa correcta es bloquearse y ser despertado por quien produce la condición.

wait + notify

Una std::condition_variable se usa siempre junto a un std::mutex y una variable que describe la condición:

#include <mutex>
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
bool piezaLista = false;                 // la condición

void hPrensa() {                         // CONSUMIDOR de la señal
    std::unique_lock<std::mutex> lk(mtx);
    cv.wait(lk, [] { return piezaLista; });   // duerme hasta piezaLista == true
    // aquí ya hay pieza: trabajar con ella
}

void hCinta() {                          // PRODUCTOR de la señal
    // ... la cinta trae la pieza ...
    {
        std::lock_guard<std::mutex> lk(mtx);
        piezaLista = true;               // 1) cambia la condición
    }
    cv.notify_one();                     // 2) despierta a un esperando
}

La secuencia siempre es la misma: cambiar la condición bajo el mutex y después notificar. El que espera usa wait con predicado, que equivale a:

while (!predicado())     // comprueba la condición
    cv.wait(lk);         // si no se cumple, suelta el mutex y duerme

Por qué el predicado es obligatorio

notify_one vs notify_all

LlamadaDespiertaÚsalo cuando…
notify_one()A un hilo esperando (si hay alguno)La condición sirve para uno solo: una pieza, un hueco.
notify_all()A todos los hilos esperandoLa condición puede servir a varios a la vez, o cambia de tipo (p. ej. parada general).

Esperar con límite de tiempo

En una instalación real no se espera eternamente: si un sensor no responde en 5 s hay alarma. Las variantes temporizadas devuelven false si se agota el tiempo:

std::unique_lock<std::mutex> lk(mtx);
if (!cv.wait_for(lk, std::chrono::seconds(5),
                 [] { return piezaLista; })) {
    // TIMEOUT: la pieza no llegó → tratar como avería
}

Dónde las usarás

🔥 Error típico

Notificar sin haber cambiado la condición, o cambiarla sin mutex: el esperando puede despertar, ver que la condición sigue siendo falsa y volver a dormir… o perder la señal para siempre. La receta es invariable: mutex → cambiar condición → soltar → notify.