quinta-feira, 7 de maio de 2009

O Problema do Barbeiro Adormecido

Outro problema clássico de CIP consistem em uma barbearia com um barbeiro, um série de cadeiras e clientes. Os pontos abaixo definem o problema:
- Cada vez que o barbeiro termina de cortar um cabelo e não existe clientes esperando, ele adormece.
- Cada vez que um cliente chega à barbearia e vê que nem uma cadeira está vazia ele não entra na barbearia e vai embora
- Quando um consumidor que está sentado na cadeira esperando vê que o barbeiro terminou de cortar um cabelo, ele tenta ser o próximo a ter o cabelo cortado.
A problemática consiste em programar consumidores e barbeio evitando condições de corrida.
A solução aplicada utiliza-se de três semáforos:

clientes - conta o número de clientes;
barbeiros - conta o número de barbeiros disponíveis.
mutex - para realizar exclusão múltipla para acesso da variável que define o número de clientes esperando;

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>

#define CADEIRAS 5 //numero de cadeiras

sem_t clientes; //semaforo para numero de clientes
sem_t barbeiros; //semaforo para numero de barbeiros
sem_t mutex; //mutex para acesso à numero de clientes esperando
int n_espera = 0; //numero de clientes esperando

pthread_t t_barbeiro; //thread para o barbeiro
int n_cortados = 0; // numero de cabelos cortados

void
cabelo_cortado(int i_con);

void
cortar_cabelo();
void
*barbeiro ();
void
*consumidor (void *i_cons);

main
()
{


int
res; //variáveis para controle de loop e validação da criação de threads e semaforos
int j;


//criação do semáforo mutex
res = sem_init(&mutex, 0, 1);

if
(res!= 0 ){
perror("\nFalha na criacao de mutex");

exit(EXIT_FAILURE);
}


//criação do semáfor de clientes
res = sem_init(&clientes, 0, 0);

if
(res!= 0 ){
perror("\nFalha na criacao do semaforo de clientes");

exit(EXIT_FAILURE);
}


//Iniciação da semáforo de barbeiro
res = sem_init(&barbeiros, 0, 0);

if
(res!= 0 ){
perror("\nFalha no semaforo de barbeiros");

exit(EXIT_FAILURE);
}


//Criação da thread do barbeiro
res = pthread_create(&t_barbeiro, NULL, barbeiro, (void *)&j);
if
(res!= 0 ){

perror("\nFalha na criacao da thread de barbeiro");
exit(EXIT_FAILURE);
}


int
n = 20;// numero de clientes

void *resultado_thread[n];
void
*resultado_thread_barbeiro;
pthread_t t[n]; //vetor das threads

int aux[n];

//criação das threads
for (j = 0 ; j<n; j++)
{


aux[j] = j;
sleep(2.f); //intervalo entre a chegada de consumdores
res = pthread_create(&t[aux[j]], NULL, consumidor, (void *)&aux[j]);
if
(res!= 0 ){

perror("\nFalha na criacao da thread");
exit(EXIT_FAILURE);
}


}


//join na thread do barbeiro
res = pthread_join(t_barbeiro, &resultado_thread_barbeiro);
if
(res!= 0 ){

perror("\nFalha no thread join");
exit(EXIT_FAILURE);

}


//join nas threads de clientes
for (j = 0 ; j<n; j++)
{

res = pthread_join(t[j], &resultado_thread[j] );
if
(res!= 0 )
{


perror("\nFalha no thread join do consumidor" );
exit(EXIT_FAILURE);
}
}

return
0;
}



//função da thread do barbeiro
void *barbeiro()
{


while
(1) {
sem_wait(&clientes); //dorme se clientes for 0

sem_wait(&mutex); // pega acesso ao numero de clientes esperando
n_espera = n_espera +(-1); //decrementa clientes

sem_post(&barbeiros); // o barbeiro está livre
sem_post(&mutex); //libera o acesso ao numero de clientes esperando
cortar_cabelo(); //corta o cabelo

}
pthread_exit("exit from thread");
}


void
*consumidor(void *i_con)
{


int
i = *(int *)i_con;
sem_wait(&mutex); //pega acesso exclusivo ào numero de clientes esperando

if (n_espera < CADEIRAS) { //verifica se tem cadeiras vagas
n_espera = n_espera + 1; //entra e incrementa numero de clientes esperando

printf("\nConsumidor %d entra na barbearia", i);
sem_post(&clientes); //acorda barbeiro se necessário
sem_post(&mutex); //libera acesso exclusivo à numero de clientes esperando

sem_wait(&barbeiros); //dorme se o barbeiro não está disponivel
cabelo_cortado(i); //se levanta e corta o cabelo
} else {

printf("\nConsumidor %d viu que estava cheiro e foi embora", i);
sem_post(&mutex); //se não possui espaço vai embroa
}

pthread_exit("exit from thread");
}


void
cabelo_cortado(int i_con){
printf("\nConsumidor %d foi cortar o cabelo", i_con);
}


void
cortar_cabelo(){
n_cortados++;
sleep(3.f);
printf("\nBarbeiro terminou corte de cabelo n %d", n_cortados);
}


No primeiro teste realizado, foram produzidos 20 clientes com intervalo de 2 s entre eles e o corte durando 3 s, assim a maior parte deles teve o cabelo cortado. O resultado abaixo confirma o esperado.


Consumidor 0 entra na barbearia
Consumidor 0 foi cortar o cabelo
Consumidor 1 entra na barbearia
Barbeiro terminou corte de cabelo n 1
Consumidor 1 foi cortar o cabelo
Consumidor 2 entra na barbearia
Barbeiro terminou corte de cabelo n 2
Consumidor 2 foi cortar o cabelo
Consumidor 3 entra na barbearia
Consumidor 4 entra na barbearia
Barbeiro terminou corte de cabelo n 3
Consumidor 3 foi cortar o cabelo
Consumidor 5 entra na barbearia
Barbeiro terminou corte de cabelo n 4
Consumidor 4 foi cortar o cabelo
Consumidor 6 entra na barbearia
Consumidor 7 entra na barbearia
Barbeiro terminou corte de cabelo n 5
Consumidor 5 foi cortar o cabelo
Consumidor 8 entra na barbearia
Barbeiro terminou corte de cabelo n 6
Consumidor 6 foi cortar o cabelo
Consumidor 9 entra na barbearia
Consumidor 10 entra na barbearia
Barbeiro terminou corte de cabelo n 7
Consumidor 7 foi cortar o cabelo
Consumidor 11 entra na barbearia
Barbeiro terminou corte de cabelo n 8
Consumidor 8 foi cortar o cabelo
Consumidor 12 entra na barbearia
Consumidor 13 entra na barbearia
Barbeiro terminou corte de cabelo n 9
Consumidor 9 foi cortar o cabelo
Consumidor 14 entra na barbearia
Barbeiro terminou corte de cabelo n 10
Consumidor 10 foi cortar o cabelo
Consumidor 15 entra na barbearia
Consumidor 16 viu que estava cheiro e foi embora
Barbeiro terminou corte de cabelo n 11
Consumidor 11 foi cortar o cabelo
Consumidor 17 entra na barbearia
Barbeiro terminou corte de cabelo n 12
Consumidor 12 foi cortar o cabelo
Consumidor 18 entra na barbearia
Consumidor 19 viu que estava cheiro e foi embora
Barbeiro terminou corte de cabelo n 13
Consumidor 13 foi cortar o cabelo
Barbeiro terminou corte de cabelo n 14
Consumidor 14 foi cortar o cabelo
Barbeiro terminou corte de cabelo n 15
Consumidor 15 foi cortar o cabelo
Barbeiro terminou corte de cabelo n 16
Consumidor 17 foi cortar o cabelo
Barbeiro terminou corte de cabelo n 17
Consumidor 18 foi cortar o cabelo

O segundo teste foi feito produzindo-se todos os clientes sem intervalo. O esperado é que o primeiro cliente entre na barbearia e tenha logo seu cabelo, os próximos cinco entram ficam esperando até cortar o cabelo e os demais chegam à barbearia mas vão embora quando vêem que não tem cadeira vazia. O resultado abaixo confirma o esperado:

Consumidor 0 entra na barbearia
Consumidor 0 foi cortar o cabelo
Consumidor 1 entra na barbearia
Consumidor 2 entra na barbearia
Consumidor 3 entra na barbearia
Consumidor 4 entra na barbearia
Consumidor 5 entra na barbearia
Consumidor 6 viu que estava cheiro e foi embora
Consumidor 7 viu que estava cheiro e foi embora
Consumidor 8 viu que estava cheiro e foi embora
Consumidor 9 viu que estava cheiro e foi embora
Consumidor 10 viu que estava cheiro e foi embora
Consumidor 11 viu que estava cheiro e foi embora
Consumidor 12 viu que estava cheiro e foi embora
Consumidor 13 viu que estava cheiro e foi embora
Consumidor 14 viu que estava cheiro e foi embora
Consumidor 15 viu que estava cheiro e foi embora
Consumidor 16 viu que estava cheiro e foi embora
Consumidor 17 viu que estava cheiro e foi embora
Consumidor 18 viu que estava cheiro e foi embora
Consumidor 19 viu que estava cheiro e foi embora
Barbeiro terminou corte de cabelo n 1
Consumidor 1 foi cortar o cabelo
Barbeiro terminou corte de cabelo n 2
Consumidor 2 foi cortar o cabelo
Barbeiro terminou corte de cabelo n 3
Consumidor 3 foi cortar o cabelo
Barbeiro terminou corte de cabelo n 4
Consumidor 4 foi cortar o cabelo
Barbeiro terminou corte de cabelo n 5
Consumidor 5 foi cortar o cabelo

Um comentário:

  1. Gostaria de saber o porque de ta dando esse erro:

    error: invalid conversion from ‘void* (*)()’ to ‘void* (*)(void*)’

    error: initializing argument 3 of ‘int pthread_create(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*)’

    ResponderExcluir