Last active
July 22, 2021 00:17
-
-
Save pr00thmatic/70d0418a495b24a79a43 to your computer and use it in GitHub Desktop.
El problema de los filósofos hambrientos (Dining Philosophers Problem). Comentado en español.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Name : Dining Philosophers Problem | |
Author : jishnu7 | |
Web : http://thecodecracker.com | |
Date : 26-Sep-2010 | |
Description : C Program to solve Dining philosophers problem | |
License : GNU GPL License | |
Traducido al español y comentado por Vengadora. | |
*/ | |
//<importando librerías> | |
#include <stdio.h> //printf: imprimir en salida estándar (consola) | |
#include <semaphore.h> //semáforos! sem_t, sem_init, ... etc ... | |
#include <pthread.h> //pthreads! pthread_create, ... etc ... | |
//</importando librerías> | |
//<declaración de constantes> | |
#define CORTO 2 | |
#define NORMAL 3 | |
#define LARGO 4 | |
#define N_FILOSOFOS 5 | |
#define PENSANDO 0 | |
#define HAMBRIENTO 1 | |
#define COMIENDO 2 | |
#define IZQUIERDA ((id_fi+4)%N_FILOSOFOS) | |
#define DERECHA ((id_fi+1)%N_FILOSOFOS) | |
//</declaración de constantes> | |
sem_t mutex; //indica si algún filósofo está en un "proceso crítico". | |
/* | |
el proceso crítico sucede mientras algún filósofo se pone hambriento o_O | |
parece que los filósofos no pueden ponerse hambrientos al mismo tiempo. | |
Cuando a un filósofo le da hambre, todos esperan hasta que éste revise | |
si hay disponible un tenedor. Cuando termina de revisar, todos vuelven | |
a su trabajo. | |
*/ | |
sem_t S[N_FILOSOFOS]; //S[i] está rojo cuando el iésimo filósofo está hambriento | |
//<declaración de los métodos que usaremos>... | |
void * ciclo_de_vida_del_filosofo(void *num); | |
void hambre(int); | |
void buen_provecho(int); | |
void comprobar_tenedores(int); | |
//</declaración de los métodos que usaremos>... | |
int estado[N_FILOSOFOS]; | |
int id_fi[N_FILOSOFOS]={0, 1, 2, 3, 4}; | |
int main() | |
{ | |
int i; | |
pthread_t thread_id[N_FILOSOFOS]; //huh? '¬' | |
//iniciar el semáforo llamado "mutex" declarado en l.32 | |
sem_init(&mutex,0,1); | |
for(i=0; i<N_FILOSOFOS; i++) | |
sem_init(&S[i],0,0); //iniciar cada uno de los semáfaros de hambre | |
for(i=0; i<N_FILOSOFOS; i++) { //crea a los filósofos | |
pthread_create(&thread_id[i], //huh? '¬' | |
NULL, //huh?!?! DX | |
ciclo_de_vida_del_filosofo, //el método que ejecutará el thread. | |
&id_fi[i]); //el argumento que acepta el método (puntero!!) | |
/* | |
Cada filósofo es un thread. al thread, se le envía el método que | |
se supone que debería ejecutar el hilo | |
*/ | |
printf("El filósofo %d está pensando \n", i+1); //los filósofos nacen pensando. | |
} | |
for(i=0; i<N_FILOSOFOS; i++) | |
pthread_join(thread_id[i], NULL); //ponemos a todos los threads juntos o_O | |
} | |
/* | |
un puntero de tipo void, es una especie de genericidad primitiva. | |
c no tiene objetos!! pero tiene varios trucos geniales para simular | |
muchas propiedades de los objetos. Este es uno de ellos! | |
un puntero de tipo void, se puede castear a cualquier otro tipo de datos. | |
algo así como el "Object" de Java. | |
*/ | |
// Este es el comportamiento del filósofo... | |
void *ciclo_de_vida_del_filosofo(void *num) | |
{ | |
while(1){ //mientras el filósofo viva | |
int *i = num; | |
printf("el filósofo %d ha reiniciado su ciclo de vida!\n", *i+1); | |
sleep(LARGO); | |
hambre(*i); //le da hambre | |
sleep(CORTO); | |
buen_provecho(*i); //sacia su hambre y vuelve a pensar. | |
} | |
} | |
void hambre(int id_fi) | |
{ | |
sem_wait(&mutex); | |
/* | |
filósofo id_fi dice: | |
"Esto es un proceso crítico! acaba de darme hambre y voy a | |
revisar los tenedores para ver si puedo comer... por favor | |
esperen a que yo termine de revisar los tenedores para que | |
ustedes puedan anunciar que están hambrientos y revisar | |
los tenedores. | |
*/ | |
//parece que esto previene que los filósofos se mueran de hambre | |
//por esperar demasiado ·o· | |
estado[id_fi] = HAMBRIENTO; //se pone hambriento | |
printf("El filósofo %d tiene hambre\n", id_fi+1); | |
comprobar_tenedores(id_fi); //revisa los tenedores | |
sem_post(&mutex); | |
/* | |
mi proceso crítico acabó! sigan con sus vidas ;D | |
*/ | |
sem_wait(&S[id_fi]); | |
/* | |
y ahora me pongo a comer hasta que esté saciado. Cuando esté saciado, | |
S[id_fi] se pondrá verde, y podré acabar este proceso. | |
*/ | |
} | |
/* | |
comprueba si el filósofo puede comer | |
*/ | |
void comprobar_tenedores(int id_fi) | |
{ | |
if (estado[id_fi] == HAMBRIENTO && //si tengo hambre | |
estado[IZQUIERDA] != COMIENDO && | |
/* | |
si el filósofo izquierdo no está comiendo quiere decir que | |
el tenedor izquierdo está disponible.. | |
*/ | |
estado[DERECHA] != COMIENDO) { | |
/* | |
si el filósofo derecho no está comiendo quiere decir que | |
el tenedor derecho está disponible.. | |
*/ | |
/* | |
y si todaas estas condiciones se cumplen, quiere decir que | |
puedo comenzar a comer! YAY! :9 | |
*/ | |
estado[id_fi] = COMIENDO; //me pongo a comer | |
sleep(NORMAL); | |
printf("El filósofo %d toma el tenedor %d y %d\n", | |
id_fi+1, IZQUIERDA+1, DERECHA+1); | |
sleep(CORTO); | |
printf("El filósofo %d está comiendo\n", id_fi+1); | |
sem_post(&S[id_fi]); //terminé de comer!! ^w^ (ver l.108) | |
} | |
} | |
/* | |
Cuando el filósofo deje de comer, debe poner los cubiertos en la mesa | |
de nuevo... | |
*/ | |
void buen_provecho(int id_fi) { | |
sem_wait(&mutex); | |
printf("El filósofo %d está soltando los tendores %d y %d\n", | |
id_fi+1, IZQUIERDA+1, DERECHA+1); | |
/* | |
Estoy entrando en un proceso crítico! estoy desocupando los | |
tenedores que ocupé. por favor, nadie haga nada crítico | |
mientras hago esto... | |
*/ | |
estado[id_fi] = PENSANDO; | |
printf("El filósofo %d está pensando\n", id_fi+1); | |
/* | |
barriga llena, corazón contento :3 ahora puedo volver a pensar. | |
*/ | |
/* | |
Avisa a los filósofos que PODRÍAN necesitar los tenedores que estaba | |
usando, que los tenedores ya están disponibles. | |
*/ | |
comprobar_tenedores(IZQUIERDA); | |
comprobar_tenedores(DERECHA); | |
/* | |
si los filósofos están hambrientos, prestarán atención al aviso! | |
de lo contrario, se irá por falso. (ver l.120) | |
*/ | |
sem_post(&mutex); | |
/* | |
terminé el proceso crítico! sigan con sus vidas ^w^ | |
*/ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
oh, btw, el comando de compilación es:
gcc -lpthread solution.c -o solution