Barbeiro Sonolento

INTRODUÇÃO

O problema do barbeiro sonolento é outro clássico problema de comunicação interprocessos.
Em uma barbearia há alguns barbeiros com suas cadeiras de barbeiro e N cadeira para eventuais clientes esperarem a vez. Quando não há clentes, o barbeiro senta na cadeira e cai no sono. Quando chega um clente, ele precisa acordar o barbeiro. Se outros clientes chegarem enquanto o barbeiro estiver cortando o cabelo de um clente, eles sentarão ou sairão da barbearia, dependendo das vagas nas cadeiras de espera.

O problema está em sincronizar os processos, programar barbeiro e clente sem cair em condições de disputa.

IMPLEMENTAÇÃO

Para implementar o problema do barbeiro sonolento, o requisito era utilização de threads.

/* ***********************************************************
Implementação da solução do problema barbeiro sonolento
utilizando thread
 
O programa recebe 2 parametro:
 - primeiro corresponde ao número de barbeiros
 - segundo corresponde ao número de cadeiras de espera
 
Tiago Porto, Maio 2009
 
*********************************************************** */
 
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <ctype.h>
#include <semaphore.h>
 
#define TRUE 1
#define FALSE 0
#define MAX 100
 
void *barber(void *arg);
void *custumer(void *arg);
void get_haircut();
void cut_hair(int i);
 
/* Variáveis globais */
sem_t mutex, custumers, barbers;
int waiting = 0, chairs;
 
main(int argc, void* argv[]){
    int i, res1, res2, res3, k, m;
    char c[100];
    pthread_t barber_thread[MAX], customer_thread[MAX];
    chairs = atoi(argv[2]);
    /* Inicia os semáforos */
    res1=sem_init(&mutex, 0, 1);
    res2=sem_init(&custumers, 0, 0);
    res3=sem_init(&barbers, 0, 0);
    if(res1!=0 || res2!=0 || res3!=0){
        perror("Falha na inicializacao do semaforo");
        exit(1);
    }
    /* Criando os barbeiros */ 
    printf("Criando os barbeiros\n");
    for(i=0; i<atoi(argv[1]); i++){
        /* Cria as threads para barbeiro */
        res1 = pthread_create(&barber_thread[i], NULL, barber, (void *)i);
        if(res1!=0){
            perror("Falha na inicializacao dos barbeiros");
            exit(1);
        }
    }
    /* Lendo um numero de clientes que vão entrar de uma vez e os criando*/
    k=0;
    while (TRUE) {
        fgets(c, MAX, stdin);
        m=atoi(c);
        if (m>0){
            for(i=k; i<m+k; i++) {
                /* Cria as thread para cliente */
                res1 = pthread_create(&customer_thread[i-k], NULL, custumer, (void *)i);
                if(res1!=0){
                    perror("Falha na inicializacao de cliente");
                    exit(1);
                }
            }
            k=i;
        }
    }
 
}
/* Função do barbeiro */
void *barber(void *arg){
    int i = (int)arg;
    printf("Barbeiro %d criado\n", i);
    usleep(rand()%10000);
    while(TRUE){
        sem_wait(&custumers);
        printf("Barbeiro %d acordado...\n", i);
        sem_wait(&mutex);
        waiting--;
        sem_post(&barbers);
        sem_post(&mutex);
        cut_hair(i);
    }
}
/* Função do cliente */
void *custumer(void *arg){
    int i = (int)arg;
    usleep(rand()%10000);
    sem_wait(&mutex);
    printf("Cliente %d entrou\n", i);
    if (waiting < chairs) {
        waiting++;
        sem_post(&custumers);
        sem_post(&mutex);
        sem_wait(&barbers);
        get_haircut(i);
        printf("Cliente %d cortou o cabelo\n", i);
    } else {
        sem_post(&mutex);
        printf("Cliente %d saiu chateado\n", i);
    }
    pthread_exit(NULL);
}
/* Função que o barbeiro corta os cabelos */
void cut_hair(int i){
    printf("Barbeiro %d cortando cabelo...\n", (int)i);
    usleep(rand()%100000);
}
/* Função que o cliente adquire um corte de cabelo */
void get_haircut(int i){
    printf("Cliente %d cortando cabelo\n", i);
    usleep(rand()%10000);
}

TESTES

Condições: 2 barbeiros e 1 cadeira de espera
Teste 1: 4 clientes criados
Teste 2: 3 clientes criados

$ ./barbeiro_sonolento 2 1
Criando os barbeiros
Barbeiro 0 criado
Barbeiro 1 criado
4
Cliente 0 entrou
Barbeiro 0 acordado...
Barbeiro 0 cortando cabelo...
Cliente 0 cortando cabelo
Cliente 1 entrou
Barbeiro 1 acordado...
Barbeiro 1 cortando cabelo...
Cliente 1 cortando cabelo
Cliente 2 entrou
Cliente 3 entrou
Cliente 3 saiu chateado
Barbeiro 0 acordado...
Barbeiro 0 cortando cabelo...
Cliente 2 cortando cabelo
3
Cliente 5 entrou
Barbeiro 0 acordado...
Barbeiro 0 cortando cabelo...
Cliente 5 cortando cabelo
Cliente 4 entrou
Barbeiro 1 acordado...
Barbeiro 1 cortando cabelo...
Cliente 4 cortando cabelo
Cliente 6 entrou
Barbeiro 1 acordado...
Barbeiro 1 cortando cabelo...
Cliente 6 cortando cabelo
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License