Patrones clásicos

Barrera y rendezvous

A veces los hilos no intercambian datos: solo necesitan esperarse. Una barrera es un punto donde N hilos deben presentarse todos antes de que cualquiera siga; un rendezvous es la cita entre dos. En planta aparecen en fases de proceso, lotes y arranques coordinados.

La instalación en acción

Tres tolvas se llenan a ritmos distintos, pero descargan solo cuando las tres están listas: la compuerta se abre a la vez para todas. Arranca la simulación y observa cómo las tolvas que llegan antes esperan en la barrera.

Consejo: el indicador «tolvas en la barrera» muestra cuántas esperan a la última.

Barrera simple (un solo uso)

Semaforo sLlegada(0);      // señales de llegada
Semaforo sApertura(0);     // permiso para continuar
std::mutex m;
int nLlegados = 0;
constexpr int N = 4;       // hilos que deben encontrarse

void esperaBarrera() {
    {
        std::lock_guard<std::mutex> lk(m);
        nLlegados++;
    }
    sLlegada.signal();                    // «ya estoy»

    if (nLlegados == N) {                 // el último en llegar
        for (int i = 0; i < N; i++)
            sApertura.signal();           // abre la barrera para todos
    } else {
        sApertura.wait();                 // los demás esperan
    }
}

Cada hilo llama a esperaBarrera(); ninguno pasa hasta que hayan llegado los N. Ejemplo: cuatro dosificadores que deben descargar sus ingredientes a la vez en la mezcladora.

Barrera reutilizable (por fases)

Si el proceso tiene fases (llenado → calentado → mezclado) y los hilos deben sincronizarse al final de cada fase, la barrera debe «rearmarse». std::barrier de C++20 lo da hecho:

#include <barrier>

std::barrier finDeFase(4);          // 4 hilos participantes

void hEstacion() {
    while (true) {
        trabajarEnLaFase();
        finDeFase.arrive_and_wait();  // espera a los demás y rearma
    }
}

Rendezvous entre dos hilos

Es la barrera de dos, pero con semáforos queda más transparente y permite que cada hilo anuncie su llegada y espere la del otro:

Semaforo sLlegadaA(0), sLlegadaB(0);

void hA() { punto1(); sLlegadaA.signal(); sLlegadaB.wait(); punto2(); }
void hB() { punto1(); sLlegadaB.signal(); sLlegadaA.wait(); punto2(); }

Aplicación: el robot y la prensa deben terminar sus movimientos antes de abrir la guarda de seguridad.

El grupo exacto: «entran de tres en tres»

Variante del cuaderno (ej60): una máquina de mantenimiento solo opera sobre grupos de 3 robots del mismo modelo. Se combina un semáforo contador que deja pasar de tres en tres con un mecanismo de aviso al tercero:

Semaforo sGrupo(3);          // solo pasan 3
Semaforo sEntra(0);          // aviso del tercero a los otros dos
std::mutex mtx;
int nPreparados = 0;

void esperaGrupo() {
    sGrupo.wait();                     // tercer wait deja el semáforo en 0
    {
        std::lock_guard<std::mutex> lk(mtx);
        nPreparados++;
        if (nPreparados == 3) {
            sEntra.signal();           // el tercero abre
            sEntra.signal();
        }
    }
    if (nPreparados < 3) sEntra.wait();  // los dos primeros esperan
}
💡 Cuál elegir

¿N hilos se esperan una vez? Barrera simple. ¿Se esperan en cada fase? std::barrier. ¿Dos hilos se citan? Rendezvous con dos semáforos. ¿Entran en grupos de K? Semáforo contador K + aviso del último.