Soluciones concurrentes al problema de los filósofos comensales: monitores, semáforos y paso de mensajes

Informática5,65 KB

Implementaciones corregidas del problema de los filósofos comensales

Introducción

El siguiente documento presenta tres implementaciones en pseudocódigo del problema de los filósofos comensales: una usando monitores, otra con semáforos y una tercera basada en comunicación por mensajes. He corregido errores ortográficos, gramaticales y de mayúsculas/minúsculas, ajustado los identificadores y la sintaxis de pseudocódigo para mayor claridad, sin eliminar ni omitir contenido original.

1. Implementación con monitor (pseudocódigo corregido)

Monitor que gestiona la obtención y liberación de tenedores evitando condiciones de carrera.

monitor comida_filosofo;

enum estado_t { PENSANDO, HAMBRIENTO, COMIENDO };
estado_t estado[5];
condition requiereTenedor[5];

void obtieneTenedores(int i) {
    estado[i] = HAMBRIENTO;
    // Si alguno de los vecinos está comiendo, esperar
    if ((estado[(i + 1) % 5] == COMIENDO) || (estado[(i + 4) % 5] == COMIENDO))
        wait(requiereTenedor[i]);
    estado[i] = COMIENDO;
}

void liberaTenedor(int i) {
    estado[i] = PENSANDO;
    // Despertar al vecino derecho si puede comer
    if ((estado[(i + 1) % 5] == HAMBRIENTO) && (estado[(i + 2) % 5] != COMIENDO))
        signal(requiereTenedor[(i + 1) % 5]);
    // Despertar al vecino izquierdo si puede comer
    if ((estado[(i + 4) % 5] == HAMBRIENTO) && (estado[(i + 3) % 5] != COMIENDO))
        signal(requiereTenedor[(i + 4) % 5]);
}

// Inicialización
for (int i = 0; i < 5; i++) {
    estado[i] = PENSANDO;
    // requiereTenedor[i] está declarado como condition; su inicialización depende
    // de la implementación del monitor (no es necesario inicializar aquí).
}

void filosofo(int k) {
    while (true) {
        piensa();
        comida_filosofo.obtieneTenedores(k);
        come();
        comida_filosofo.liberaTenedor(k);
    }
}

// main: lanzar 5 filósofos en paralelo
main {
    paralelo(filosofo[0], filosofo[1], filosofo[2], filosofo[3], filosofo[4]);
}

2. Implementación con semáforos

Versión clásica que evita deadlock alterando el orden de adquisición de tenedores según paridad.

semaforo tenedor[5] = {1, 1, 1, 1, 1};

void filosofoImpar(int i) {
    while (true) {
        piensa();
        wait(tenedor[i]);
        wait(tenedor[(i + 1) % 5]);
        come();
        signal(tenedor[(i + 1) % 5]);
        signal(tenedor[i]);
    }
}

void filosofoPar(int j) {
    while (true) {
        piensa();
        // Orden invertido para evitar interbloqueo
        wait(tenedor[(j + 1) % 5]);
        wait(tenedor[j]);
        come();
        signal(tenedor[j]);
        signal(tenedor[(j + 1) % 5]);
    }
}

// main: lanzar filósofos (par/ímpar según índice)
main {
    paralelo(filosofo[0], filosofo[1], filosofo[2], filosofo[3], filosofo[4]);
}

3. Implementación basada en paso de mensajes (buzones y controlador)

Versión con envío y recepción de mensajes entre filósofos y un proceso controlador central que concede tenedores.

void filosofo(int i) {
    mensaje fmsg;
    while (true) {
        piensa();
        fmsg = "comer";
        send(pido_tenedores[i], fmsg);
        receive(tenedor_concedido[i], fmsg);
        come();
        fmsg = "dormir";
        send(suelto_tenedores[i], fmsg);
    }
}

void controlador() {
    // true indica tenedor disponible (1)
    bool tenedores[5] = { true, true, true, true, true };
    int contador;
    mensaje cmsg;
    while (true) {
        select {
            // recibir peticiones y conceder si ambos tenedores están libres
            for (int cont = 0; cont < 5; cont++) replicate {
                when (tenedores[cont] == true && tenedores[(cont + 1) % 5] == true)
                    receive(pido_tenedores[cont], cmsg);
                    tenedores[cont] = false;
                    tenedores[(cont + 1) % 5] = false;
                    send(tenedor_concedido[cont], cmsg);
                or
                // recibir liberaciones y marcar tenedores como libres
                for (int cont = 0; cont < 5; cont++) replicate {
                    receive(suelto_tenedores[cont], cmsg);
                    tenedores[cont] = true;
                    tenedores[(cont + 1) % 5] = true;
                }
            }
        }
    }
}

// main: crear buzones y lanzar filósofos y controlador
main {
    create_buzon(pido_tenedores);
    create_buzon(tenedor_concedido);
    create_buzon(suelto_tenedores);
    paralelo(filosofo[0], filosofo[1], filosofo[2], filosofo[3], filosofo[4], controlador);
}

Notas y correcciones realizadas

  • Se corrigieron errores ortográficos (por ejemplo, «hambiento» → «hambriento», «obitiene» → «obtiene», «mensage» → «mensaje»).
  • Se unificaron y aclararon identificadores para mayor coherencia (por ejemplo, requiereTenedor → requiereTenedor o tenedor_concedido).
  • Se ajustó la notación de índices con módulo para evitar referencias fuera de rango: se usa (i + 1) % 5, (i + 4) % 5, etc.
  • Se mantuvo todo el contenido original y su estructura lógica, pero se presentó en pseudocódigo más legible y correcto sintácticamente.
Recomendaciones

Dependiendo del entorno (lenguaje y runtime) que utilice, adapte la nomenclatura de wait, signal, send y receive, así como la creación de buzones y la construcción paralelo(...). Estas versiones son pseudocódigo didáctico para ilustrar alternativas de sincronización.

Fin del documento

Descargar

PDF Word HTML