Las barreras sincronizan grupos de hilos al final de una etapa: todos deben llegar antes de que alguno continúe. Windows ofrece SYNCHRONIZATION_BARRIER; también se puede implementar una barrera manual con contador y variables de condición.
Es un punto de encuentro: varios hilos avanzan en paralelo y se detienen en la barrera hasta que todos lleguen. Luego, todos arrancan la siguiente etapa juntos, evitando que alguno se adelante.
SYNCHRONIZATION_BARRIER en Windows o implementación manual con contador + condition variableWindows incluye SYNCHRONIZATION_BARRIER para facilitar esta coordinación. Cuando no está disponible (versiones antiguas) se puede crear una barrera manual con contador protegido por CRITICAL_SECTION y variables de condición para esperar y despertar.
InitializeSynchronizationBarrier() y EnterSynchronizationBarrier()InitializeSynchronizationBarrier configura la barrera con el número de participantes. Cada hilo llama a EnterSynchronizationBarrier al finalizar una etapa; la función bloquea hasta que todos lleguen y luego libera a todos para la siguiente ronda.
En algoritmos por fases (por ejemplo, simulaciones por iteraciones o pipelines), la barrera asegura que todos los hilos terminen la fase actual antes de empezar la siguiente, manteniendo consistencia de datos compartidos.
Común en métodos iterativos (Jacobi, Gauss-Seidel), juegos de celdas (Game of Life), render distribuido por tiles, y pipelines donde cada etapa depende de la salida completa de la anterior.
El programa crea varios hilos que procesan segmentos de un array en varias etapas. Al final de cada etapa todos llaman a EnterSynchronizationBarrier para esperar al resto. El hilo principal verifica el resultado final tras completar todas las fases.
#include <windows.h>
#include <process.h>
#include <stdio.h>
#include <stdlib.h>
#define HILOS 4
#define N 16
#define ETAPAS 3
static int datos[N];
static SYNCHRONIZATION_BARRIER barrera;
unsigned __stdcall trabajador(void *arg) {
int id = (int)(intptr_t)arg;
int inicio = (N / HILOS) * id;
int fin = inicio + (N / HILOS);
for (int etapa = 1; etapa <= ETAPAS; etapa++) {
for (int i = inicio; i < fin; i++) {
datos[i] += etapa; /* trabajo simulado */
}
printf("[hilo %d] etapa %d completada\n", id, etapa);
EnterSynchronizationBarrier(&barrera, SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY);
}
return 0;
}
int main(void) {
for (int i = 0; i < N; i++) {
datos[i] = i;
}
if (!InitializeSynchronizationBarrier(&barrera, HILOS, -1)) {
fprintf(stderr, "No se pudo inicializar la barrera (%lu)\n", GetLastError());
return EXIT_FAILURE;
}
HANDLE hilos[HILOS] = {0};
for (int i = 0; i < HILOS; i++) {
uintptr_t h = _beginthreadex(NULL, 0, trabajador, (void *)(intptr_t)i, 0, NULL);
if (h == 0) {
fprintf(stderr, "No se pudo crear el hilo %d\n", i);
return EXIT_FAILURE;
}
hilos[i] = (HANDLE)h;
}
WaitForMultipleObjects(HILOS, hilos, TRUE, INFINITE);
DeleteSynchronizationBarrier(&barrera);
int ok = 1;
for (int i = 0; i < N; i++) {
int esperado = i + (ETAPAS * (ETAPAS + 1)) / 2; /* suma de 1..ETAPAS */
if (datos[i] != esperado) {
ok = 0;
break;
}
}
printf("Resultado final: %s\n", ok ? "correcto" : "incorrecto");
for (int i = 0; i < HILOS; i++) {
CloseHandle(hilos[i]);
}
return ok ? EXIT_SUCCESS : EXIT_FAILURE;
}
Si tu versión de Windows no soporta SYNCHRONIZATION_BARRIER, reemplaza esa API por una barrera manual: un contador protegido con CRITICAL_SECTION y dos CONDITION_VARIABLE (para esperar y para reiniciar el ciclo de espera).