O Problema do Jantar dos Filósofos é um dos problemas clássicos de CIP. Consiste basicamente em uma mesa redonda com N pratos e um garfo entre cada dois pratos. Cada filósofo se posiciona em frente de cada prato e sua vida alterna entre dois estados, comer e pensar. Para comer é necessário a utilização de dos dois garfos ao lado do prato do filósofo. Quando está com fome, o filósofo tenta pegar o garfo de um lado e, se conseguir, pega o outro garfo e come. Após um tempo, ele colocar os garfos de volta a mesa e volta à pensar. A solução para o problema consiste em fazer com que nenhum filósofo fique esperando eternamente para pegar os garfos.
A solução apresentada aqui utiliza uma atribuição de um dos três estados aos filósofos: comendo, pensando e com fome. O filósofo só passa para o estado comendo caso os dois vizinhos não estajam comendo.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
#define N 5 //numeor de filosofos
#define ESQUERDO (i+N+(-1))%(N) //indice do vizinho esquerdo
#define DIREITO (i+1)%N //indice do vizinho direto
#define PENSANDO 0 //estado pensando
#define FOME 1 //estado com fome
#define COMENDO 2 //estado comendo
int estado[N]; //vetor que guarda estado dos filosfos
sem_t mutex; //mutex para regiões críticas
sem_t s[N]; //semáforo para cada filósofo
pthread_t t[N]; //vetor de threads para filósofos
void pegar_garfos(int i);
void devolver_garfos(int i) ;
void testar(int i);
void pensar(int i);
void comer(int i);
void *filosofo (void *arg);
void imprime_estados();
int main(int argc, char *argv){
//variáveis para criação e validação das threadas
int res;
int j;
void *resultado_thread[N];
//criação de mutex
res = sem_init(&mutex, 0, 1);
if (res!= 0 ){
perror("\nFalha no semaforo");
exit(EXIT_FAILURE);
}
else printf("\n Mutex criado");
//criação do vetor de semáforos
for(j = 0; j<5; j++){
res = sem_init(&s[j], 0, 0);
if (res!= 0 ){
perror("\nFalha no semaforo");
exit(EXIT_FAILURE);
}
else printf("\nSemaforo %d criado", j);
}
//criação das threadas dos filósofos
int aux[5];
for(j = 0; j<5; j++){
aux[j] = j;
estado[j] = PENSANDO;
res = pthread_create(&t[j], NULL, filosofo, (void *)&aux[j]);
if (res!= 0 ){
perror("\nFalha na criacao da thread");
exit(EXIT_FAILURE);
}
else printf("\n Thread do filósofo %d criado", j);
}
//join nas threads dos filósofos
for(j = 0; j<5; j++){
res = pthread_join(t[j], &resultado_thread[j] );
if (res!= 0 ){
perror("\nFalha no thread join");
exit(EXIT_FAILURE);
}
}
return 0;
}
void *filosofo (void *arg)
{
int i = *(int *)arg;
while (1) { //loop infinito
pensar(i); //filósofo pensando
pegar_garfos(i); //faz tentativa de pegar garfos até conseguir
comer(i); //come
devolver_garfos(i); //devolve garfos a mesa
}
pthread_exit("exit from thread");
}
void pegar_garfos(int i) //i é o identificador do filósofo
{
sem_wait(&mutex); //entra na região crítica
estado[i] = FOME; //muda estado para fome
testar(i); //vê se é possível pegar garfos
sem_post(&mutex); //sai da região crítica
sem_wait(&s[i]); //fica bloqueado caso não tenha pego os garfos
}
void devolver_garfos(int i)
{
sem_wait(&mutex); //entra na região crítica
estado[i] = PENSANDO; //muda estado para pensando
testar(ESQUERDO); //ve se o vizinho esquerdo pode comer
testar(DIREITO); //ve se o vizinho direto pode comer
sem_post(&mutex); //sai da região critica
}
void testar(int i) /* i: filosofo number, from 0 to N−1 */
{
if (estado[i] == FOME && estado[ESQUERDO] != COMENDO && estado[DIREITO] != COMENDO) {
estado[i] = COMENDO;//come se estiver com fome e nenhum vizinho está comendo
imprime_estados(); //imprime estado dos filósofos para validar
sem_post(&s[i]);
}
}
void pensar(int i)
{
sleep(rand()%5);//pensa durante um tempo de 0 a 5 s
}
void comer(int i)
{
sleep(rand()%5);//come durante um tempo de 0 a 5s
}
void imprime_estados(){
printf("\nFilosofos: 0 1 2 3 4");
printf("\n ");
int j;
char e;
for(j = 0; j<N; j++){
if (estado[j] == PENSANDO) e = 'P';
else if (estado[j] == COMENDO) e = 'C';
else e = 'F';
printf("%c ",e);
}
}
Abaixo segue o resultado do teste realizado. São exibidos o estado de cada filósofo representado pelos caracteres:
'C' - o filósofo está comendo;
'F' - o filósofo está com fome;
'P' - o filósofo está pensando;
Mutex criado
Semaforo 0 criado
Semaforo 1 criado
Semaforo 2 criado
Semaforo 3 criado
Semaforo 4 criado
Thread do filósofo 0 criado
Thread do filósofo 1 criado
Thread do filósofo 2 criado
Filosofos: 0 1 2 3 4
P P P C P
Thread do filósofo 3 criado
Thread do filósofo 4 criado
Filosofos: 0 1 2 3 4
P C P C F
Filosofos: 0 1 2 3 4
C P F C F
Filosofos: 0 1 2 3 4
C P C P F
Filosofos: 0 1 2 3 4
C F P C F
Filosofos: 0 1 2 3 4
C F C P F
Filosofos: 0 1 2 3 4
P F C P C
Filosofos: 0 1 2 3 4
C F C P P
Filosofos: 0 1 2 3 4
P C P F P
Filosofos: 0 1 2 3 4
P C P C P
Filosofos: 0 1 2 3 4
C P P C F
Filosofos: 0 1 2 3 4
C P C P F
Filosofos: 0 1 2 3 4
P F P P C
Filosofos: 0 1 2 3 4
P C P P C
Filosofos: 0 1 2 3 4
P P C P C
Filosofos: 0 1 2 3 4
C P C F P
O teste mostra que em nenhum momento existem filósofos adjacentes comendo, sempre o vizinho de um filósofo comento está pensando ou com fome.
quinta-feira, 7 de maio de 2009
Assinar:
Postar comentários (Atom)
Nenhum comentário:
Postar um comentário