62 / Concurrencia

Semáforo

Un Semaphore de std/sync limita el número de accesos concurrentes a un recurso. sem_new(n) crea un semáforo con n permisos, sem_acquire toma un permiso (bloqueando si no hay ninguno disponible), y sem_release devuelve uno.

62-semaphore.nxFuente →
// Semaphore — limiting concurrent access to a resource
// Semáforo — limitar acceso concurrente a un recurso

import "std/sync"

// Stateful handles (Semaphore/WaitGroup/mutex_new()) are SAFE as global
// initializers — they run single-threaded before main (since v0.24.27).
// Never lazy-init them behind a READY flag: that's a data race (see LLM.md).
// ES: los handles con estado son SEGUROS como inicializadores globales —
// corren single-threaded antes de main. Nunca lazy-init detrás de un flag.
var sem: Semaphore = sem_new(2)
var done: WaitGroup = wg_new()

fn access_resource() -> int {
    sem_acquire(sem)
    print("acquired (count: " + int_to_string(sem_count(sem)) + ")")
    sleep(50)
    sem_release(sem)
    print("released")
    wg_done(done)
    return 0
}

fn main() -> int {
    // Allow at most 2 concurrent accesses
    wg_add(done, 5)

    var i: int = 0
    while i < 5 {
        thread_spawn(access_resource)
        i = i + 1
    }

    wg_wait(done)
    print("all done")
    return 0
}
Salida ilustrativastdout
acquired (count: 1)
acquired (count: 0)
released
released
acquired (count: 1)
acquired (count: 0)
released
released
acquired (count: 1)
released
all done

Cómo funciona

sem_new(2) crea un semáforo con 2 permisos. Como máximo 2 hilos pueden tener un permiso al mismo tiempo. Cuando un tercer hilo llama a sem_acquire, se bloquea hasta que uno de los dos primeros llame a sem_release.

Cinco hilos compiten por el semáforo. sem_count devuelve el número de permisos restantes, que cae a 0 cuando ambos están tomados. Después de dormir 50 milisegundos (simulando trabajo), cada hilo libera su permiso y avisa al WaitGroup.

Este patrón es útil para limitar la velocidad de acceso a recursos externos como conexiones de base de datos, descriptores de archivo o endpoints de API, donde se desea concurrencia controlada en lugar de exclusión mutua total.