RedNotes
Toggle sidebar
Iniciar sesión
Sistemas Operativos/Semáforos
Inicia sesión para editar

Un semáforo es una variable entera propuesta por E. W. Dijkstra (1965) para contar el número de "despertares" pendientes. Resuelve el problema de los despertares perdidos de sleep/wakeup descrito en Sistemas Operativos/Concurrencia.

Operaciones

Dijkstra las llamó P (proberen, probar) y V (verhogen, incrementar); Tanenbaum usa down y up:

  • down(s): si s > 0, lo decrementa y continúa. Si s == 0, el proceso se duerme sin completar el down.
  • up(s): incrementa s. Si había procesos dormidos en el semáforo, el sistema elige uno y le permite completar su down.

Ambas operaciones son indivisibles (atómicas): una vez iniciada, ningún otro proceso puede acceder al semáforo hasta que termine. Normalmente se implementan como Sistemas Operativos/Llamadas al sistema, deshabilitando brevemente las interrupciones o usando TSL/XCHG en multiprocesadores.

Tipos

  • Semáforo binario (mutex): inicializado en 1, garantiza exclusión mutua.
  • Semáforo contador: inicializado en N, cuenta recursos disponibles.

Además de exclusión mutua, los semáforos sirven para sincronización: garantizar que ciertos eventos ocurren en cierto orden.

Productor-consumidor con semáforos

const int N = 100;
typedef int semaphore;
semaphore mutex = 1;     /* controla el acceso a la región crítica */
semaphore empty = N;     /* cuenta ranuras vacías del búfer */
semaphore full  = 0;     /* cuenta ranuras llenas del búfer */

void producer(void) {
    int item;
    while (TRUE) {
        item = produce_item();
        down(&empty);
        down(&mutex);
        insert_item(item);
        up(&mutex);
        up(&full);
    }
}

void consumer(void) {
    int item;
    while (TRUE) {
        down(&full);
        down(&mutex);
        item = remove_item();
        up(&mutex);
        up(&empty);
        consume_item(item);
    }
}
  • mutex se usa para exclusión mutua.
  • full y empty se usan para sincronización.

⚠️ El orden importa

Si el productor invierte down(&empty) y down(&mutex) y el búfer está lleno, se bloquea con el mutex tomado: el consumidor nunca puede entrar y ambos quedan bloqueados para siempre. Es un interbloqueo — ver Sistemas Operativos/Interbloqueos.

Esta fragilidad motivó primitivas de más alto nivel: Sistemas Operativos/Mutex y monitores.

Semáforos en la práctica (POSIX)

sem_init, sem_wait (down), sem_post (up), sem_destroy.

#sistemas-operativos #tanenbaum #semaforos #concurrencia