Problema 3 Fabio Imada

retornar

Problema do Barbeiro Sonolento

Introdução

Continuando o estudo de threads e semáforos, será implementado o problema do barbeiro sonolento. O enunciado segue abaixo:

"O barbeiro sonolento dorme toda vez que seu salão está vazio, mas assim que alguém chega, o barbeiro volta ao trabalho. Desse modo, ele não "perde tempo" acordado.
Em seu seu salão cabem até N clientes na fila de espera. Os clientes que chegam e vêem que o salão está cheio vão embora."

Para implementar o problema, considerou-se que cada barbeiro é uma thread (considerou-se o caso de existirem mais barbeiros trabalhando no mesmo salão) e cada cliente também é uma thread.
As threads de cliente possuem um ciclo de vida curto: ou chegam ao salão e vão embora porque estava cheio, ou chegam, aguardam, cortam o cabelo e vão embora.
As threads de barbeiros

Desenvolvimento

O problema do barbeiro sonolento simula uma situacao de fila, onde os recursos (barbeiros) compartilham uma fila de acesso (sala de espera) e os processos (clientes) entram nessa fila desde que essa não esteja cheia.
Por haver esse limite, os clientes precisam saber quantas pessoas existem na sala, e por isso foi criado um contador (posteriormente o aluno descobriu que o semáforo implementado em C possui o atributo value, que executa a mesma funcao).
Foram utilizados sleeps para simular duas coisas:

  • A chegada de clientes, caso contrário a grande maioria iria embora após os N primeiros.
  • O tempo de corte de cabelo, para que os clientes não sejam imediatamente atendidos e assim acabando com a possível fila.

Portanto, os resultados apresentados utlizaram:

  • Alto tempo de corte de cabelo e pouco intervalo de chegada para que a sala enchesse e os clientes comećassem a ir embora;
  • Baixo tempo de corte e muito tempo de intervalo de chegada para que o barbeiro passasse boa parte do tempo dormindo.

Conteúdo do arquivo barbearia.c

#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
 
#define CADEIRAS 5
#define N_BARBEIROS 3
#define N_CLIENTES 55
#define TRUE 1
#define FALSE 0
 
sem_t sem_clientes;
sem_t sem_barbeiros;
sem_t mutex;
int fila_de_espera = 0;
 
void cortar_cabelo() {
    sleep(rand()%5);
}
 
void barbeiro(int i) {
    while (TRUE) {
        if (fila_de_espera == 0)
            printf("Barbeiro %d foi dormir.\n", i);
        sem_wait(&sem_clientes);
        sem_wait(&mutex);
        printf("Barbeiro %d iniciou corte de cabelo.\n", i);
        fila_de_espera -= 1;
        sem_post(&sem_barbeiros);
        sem_post(&mutex);
        cortar_cabelo();
    }
}
 
void receber_corte_de_cabelo(int i) {
    printf("Cliente %d cortou o cabelo\n", i);
}
 
void cliente(int i) {
    sem_wait(&mutex);
    if (fila_de_espera < CADEIRAS) {
        printf("%d na espera, cliente %d ira esperar\n", fila_de_espera, i);
        fila_de_espera = fila_de_espera + 1;
        sem_post(&sem_clientes);
        sem_post(&mutex);
        sem_wait(&sem_barbeiros);
        receber_corte_de_cabelo(i);
    } else {
        printf("Sem vagas, cliente %d foi embora.\n", i);
        sem_post(&mutex);
    }
    pthread_exit("Terminou!\n");
}
int main() {
 
    int res, res_parc, i;
 
    pthread_t th_customer[N_CLIENTES], th_barbeiro[N_BARBEIROS];
 
    res = 0;
    /* Inicializando semaforos */
    res_parc = sem_init(&sem_clientes, 0, 0);
    res += res_parc;
    res_parc = sem_init(&sem_barbeiros, 0, 0);
    res += res_parc;
    res_parc = sem_init(&mutex, 0, 1);
    res += res_parc;
    if (res != 0) {
        perror("Erro na inicializacao dos semaforos");
        exit(EXIT_FAILURE);
    }
    /* Inicializando threads */
    for (i = 0; i < N_BARBEIROS; i++) {
        res_parc = pthread_create(&th_barbeiro[i], NULL, (void*) barbeiro,
                (int*) (i + 1));
        res += res_parc;
    }
    for (res = 0, i = 0; i < N_CLIENTES; i++) {
        usleep(rand()%1000000);
        res_parc = pthread_create(&th_customer[i], NULL, (void*) cliente,
                (int*) (i + 1));
        res += res_parc;
    }
    if (res != 0) {
        perror("Erro em criacao de threads\n");
        exit(EXIT_FAILURE);
    }
    /* Juntando threads (as threads de barbeiro continuam indefinidamente!) */
    for (res = 0, i = 0; i < N_CLIENTES; i++) {
        res_parc = pthread_join(th_customer[i], NULL);
        res += res_parc;
    }
    if (res != 0) {
        perror("Erro em join threads\n");
        exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
}

Screenshots

A tela abaixo apresenta o comando para compilar o programa e sua execução.

barbeiro.png

A tela abaixo apresenta o programa após executar por algum tempo, com o salão cheio (intervalo de chegada de clientes menor do que intervalo de corte).

barbeiro_regime.png

A tela abaixo apresenta o programa após executar por algum tempo, com o salão vazio (intervalo de chegada de clientes maior do que intervalo de corte).

barbeiro_dormindo.png

retornar

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License