quinta-feira, 7 de maio de 2009

Problema da Barbearia utilizando threads

O problema da Barbearia possui como objetivo manter o barbeiro trabalhando enquanto houver consumidores e descansando quando não há consumidores.
Quando um consumidor chega a barbearia, ele acorda o barbeiro para obter o corte de cabelo, ou senta-se nas cadeiras para esperar se o barbeiro estiver cortando o cabelo de outra pessoa. Caso todas as cadeiras da barbearia estejam ocupadas, o consumidor simplesmente deixa o local.


Este problema é interessante, pois devemos coordenar as atividades sem gerar condições de corrida. Uma solução falha pode resultar em problemas de starvation ou de deadlock entre os processos.
O deadlock é obtido quando o consumidor fica esperando o barbeiro e o barbeiro fica esperando o consumidor.
A situação de starvation é obtida quando os consumidores não possuem uma ordem para o corte de cabelo, assim pode haver a situação em que consumidores não obtem a chance de ter seu cabelo cortado, esperando para sempre.
Em nossa solução, vamos considerar um barbeiro e vários consumidores, chegando em intervalos de tempo randômicos. O barbeiro será uma thread e cada consumidor será outra thread. Teremos semáforos para garantir que situações de deadlock não ocorram. Além disso, consideramos que o tempo para o corte de cabelo será constante para todos os consumidores. Isto pode ser alterado!

Utilizaremos as instruções sem_wait e sem_post para controlar o acesso às regiões críticas. Documentação do uso pode ser encontrada em:
http://www.opengroup.org/onlinepubs/007908775/xsh/sem_wait.html

http://www.opengroup.org/onlinepubs/007908799/xsh/sem_post.html
Para criar estes semáforos, vamos utilizar os seguintes comandos sem_t e sem_init:
http://www.opengroup.org/onlinepubs/007908775/xsh/sem_init.html

Além disso, devemos criar as threads. Isto pode ser feito utilizando os seguintes comandos:
declaração: pthread_t
criação: pthread_create() - http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_create.html

Aqui, é interessante notar que ao criarmos a thread, ela inicia sua execução. Contudo, a thread principal não pára sua execução! Assim, é necessário utilizarmos o comando pthread_join para evitar que a thread principal termine o programa, e com isso, mate todas as outras threads.
pthread_join() - http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_join.html


Para aprender mais sobre este problema, visite: http://en.wikipedia.org/wiki/Sleeping_barber_problem

Utilizando o seguinte comando:
gcc [[nome_programa.c]] -o [[nome_programa]] -lpthread
compilamos o programa e geramos o arquivo executável.
Para executar o programa, utilizamos o seguinte comando:
./[[nome_programa]]

Utilizamos o seguinte código:

//Bibliotecas utilizadas...
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>

#define CHAIRS 5 //quantidade de cadeiras na barbearia
#define CONSUMERS 100000 //quantidade total de clientes


/*
typedef int semaphore; /*os semaforos sao um tipo especial de int
semaphore customers=0; /*array para controlar o estado de todos
semaphore barbers=0;
semaphore mutex = 1; /*exclusão mutua para regioes cri­ticas
semaphore s[N]; /*um semaforo por filosofo
*/


sem_t customers; //semaforo para controlar os consumidores esperando pelo corte de cabel
sem_t barbers; //semaforo para controlar os barbeiros esperando pelos consumidores
sem_t mutex; //semaforo para exclusao mutua para regioes criticas
int waiting=0;


//prototipos...
void cut_hair();
void
get_haircut();

void
barber()
{


while
(1)
{

if
(waiting==0) printf("Barber esperando consumidores... \n"); //caso a quantidade de pessoas na barbearia seja 0

sem_wait(&customers); //down(&customers); dorme se a quantidade de consumidores for 0
sem_wait(&mutex); //down(&mutex); garante acesso exclusivo a variavel waiting
waiting=waiting-1; //diminui a quantidade de clientes esperando

sem_post(&barbers); //up(&barbers); um barbeiro esta pronto para realizar o corte de cabelo
sem_post(&mutex); //up(&mutex); libera o acesso a variavel waiting
cut_hair(); //corta o cabelo do cliente

}
}


void
customer()
{

sem_wait(&mutex); //down(&mutex); garante acesso exclusivo a variavel waiting

if(waiting<CHAIRS) //se nao houver cadeiras livres, vai embora...
{
waiting = waiting + 1; //aumenta a quantidade de clientes esperando

printf("Mais um consumidor! Total de %d consumidores esperando\n",waiting);
sem_post(&customers); //up(&customers);acorda o barbeiro avisando que temos um novo cliente
sem_post(&mutex); //up(&mutex); libera o acesso a variavel waiting

sem_wait(&barbers); //down(&barbers); espera se todos os barbeiros estiverem ocupados
get_haircut(); //obtem corte de cabelo...
}
else


{

printf("Cadeiras lotadas... vou embora\n");
sem_post(&mutex);
}
}


void
cut_hair()
{


/*Barbeiro esta cortando cabelo*/

printf("Barber is cutting hair\n");
sleep(3);
return
;
}


void
get_haircut()
{

/*Cliente esta recebendo corte de cabelo*/

sleep(3);
return
;
}


main
()
{

pthread_t barberthread, consumerthread[CONSUMERS];

int
i=0,sleeptime;


// Create independent threads each of which will execute function
/*To initialize a semaphore, use sem_init():
int sem_init(sem_t *sem, int pshared, unsigned int value);
sem_init(&sem_name, 0, 10);
*/

sem_init(&customers, 0, 0);

sem_init(&barbers, 0, 1);
sem_init(&mutex, 0, 1);

pthread_create( &barberthread, NULL,(void *) barber, NULL );

for
(i=0;i<CONSUMERS;i++)
{

sleeptime = rand()%5;

sleep(sleeptime);
pthread_create(&consumerthread[i], NULL, (void *) customer, NULL);
}


pthread_join( barberthread, NULL);
for
(i=0;i<CONSUMERS;i++){

pthread_join( consumerthread[i], NULL);
}


exit(0);
}




Assim, obtivemos o seguinte resultado:

andersonaiziro@Aaiziro:~/Documents$ ./sleepbarber
Barber esperando consumidores...
Mais um consumidor! Total de 1 consumidores esperando
Barber is cutting hair
Mais um consumidor! Total de 1 consumidores esperando
Barber is cutting hair
Mais um consumidor! Total de 1 consumidores esperando
Mais um consumidor! Total de 2 consumidores esperando
Barber is cutting hair
Mais um consumidor! Total de 2 consumidores esperando
Mais um consumidor! Total de 3 consumidores esperando
Mais um consumidor! Total de 4 consumidores esperando
Barber is cutting hair
Mais um consumidor! Total de 4 consumidores esperando
Barber is cutting hair
Mais um consumidor! Total de 4 consumidores esperando
Mais um consumidor! Total de 5 consumidores esperando
Barber is cutting hair
Mais um consumidor! Total de 5 consumidores esperando
Barber is cutting hair
Mais um consumidor! Total de 5 consumidores esperando
Cadeiras lotadas... vou embora
Barber is cutting hair
Mais um consumidor! Total de 5 consumidores esperando
Barber is cutting hair
Mais um consumidor! Total de 5 consumidores esperando
Cadeiras lotadas... vou embora
Cadeiras lotadas... vou embora
Barber is cutting hair
Mais um consumidor! Total de 5 consumidores esperando
Cadeiras lotadas... vou embora
Barber is cutting hair
Mais um consumidor! Total de 5 consumidores esperando
Cadeiras lotadas... vou embora
Barber is cutting hair
Mais um consumidor! Total de 5 consumidores esperando
Barber is cutting hair
Mais um consumidor! Total de 5 consumidores esperando
Barber is cutting hair

Nenhum comentário:

Postar um comentário