Ex1 Fabio Imada

retornar

Problema do Banheiro Compartilhado

Introdução

Continuando o estudo de threads e semáforos, foi proposto o problema de um banheiro compartilhado por homens e mulheres seguindo as seguintes regras:

  • O banheiro possui uma placa indicando seu estado atual: Vazio, Com homem ou Com mulher.
  • Quando um homem entra, nenhuma mulher pode entrar, mas os homens podem entrar a vontade, e vice-versa.

Este problema se assemelha com o problema dos leitores e escritores, sendo que seriam dois tipos de leitores, ao invés de um leitor e outro escritor.
Por isso foram utilizados 3 semáforos: Um para o acesso ao banheiro, outro para contagem de homens/mulheres no banheiro.

Desenvolvimento

Como foi dito anteriormente, o problema foi implementado com base na implementacão do leitor, por isso há a seguinte lógica por trás da implementaćão: se há uma mulher no banheiro, as que chegam depois podem entrar. A partir do momento que um homem chega, este espera para entrar e caso cheguem mulheres após isso, estas devem esperar o homem utilizar o banheiro.
Desse modo, o acesso ao banheiro não fica dominado por apenas um sexo, embora para o caso de todos cheguem "quase ao mesmo tempo" e seu tempo de processamento seja aproximadamente igual, a melhor utilizacao provavelmente seria que todos as mulheres entrassem e depois todos os homens, ou vice-versa.
Procurou-se simular uma entrada aleatória de homens e mulheres além de um tempo de uso do banheiro. Dessa forma tornou-se possível a observaćão de diferentes comportamentos, todos seguindo o desejado: uma mulher entrando e saindo, várias mulheres ao mesmo tempo, além da alternância do sinal.

Conteúdo do arquivo banheiro.c

#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#define N 20
 
sem_t homem, mulher, banheiro;
int conta_homem, conta_mulher;
void mulher_quer_entrar();
void mulher_sai();
void mulher_usa_banheiro();
void adiciona_mulher();
void homem_quer_entrar();
void homem_sai();
void homem_usa_banheiro();
void adiciona_homem();
 
int main() {
    conta_mulher = 0;
    conta_homem = 0;
    pthread_t thread[N];
 
    /* Inicializando os semaforos */
    int i, res_parc, res = 0;
    res_parc = sem_init(&homem, 0, 1);
    res += res_parc;
    res_parc = sem_init(&mulher, 0, 1);
    res += res_parc;
    res_parc = sem_init(&banheiro, 0, 1);
    res += res_parc;
    if (res != 0) {
        perror("Falha na inicializacao dos semaforos\n");
        exit(EXIT_FAILURE);
    }
 
    /* Inicializando threads */
    for (res = 0, i = 0; i < N; i++) {
        usleep(rand() % 300000);
        if (rand() % 2 != 0)
            res_parc = pthread_create(&thread[i], NULL,
                    (void*) adiciona_mulher, (int*) (i + 1));
        else
            res_parc = pthread_create(&thread[i], NULL, (void*) adiciona_homem,
                    (int*) (i + 1));
        res += res_parc;
    }
    if (res != 0) {
        perror("Erro em criacao de threads\n");
        exit(EXIT_FAILURE);
    }
    /* Juntando threads */
    for (i = 0; i < N; i++) {
        res_parc = pthread_join(thread[i], NULL);
        res += res_parc;
    }
    if (res != 0) {
        perror("Erro em join threads\n");
        exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
}
 
void mulher_quer_entrar() {
    sem_wait(&mulher);
    conta_mulher += 1;
    if (conta_mulher == 1) {
        sem_wait(&banheiro);
        printf("--------- Estado: Com mulher ---------\n");
    }
    printf("Entrou mulher, total: %d\n", conta_mulher);
    sem_post(&mulher);
}
 
void mulher_sai() {
    sem_wait(&mulher);
    conta_mulher -= 1;
    printf("Saiu mulher, total: %d\n", conta_mulher);
    if (conta_mulher == 0) {
        sem_post(&banheiro);
        printf("--------- Estado: Vazio ---------\n");
    }
    sem_post(&mulher);
}
 
void mulher_usa_banheiro() {
    usleep(rand() % 500000);
}
 
void adiciona_mulher() {
    usleep(rand() % 400000);
    mulher_quer_entrar();
    mulher_usa_banheiro();
    mulher_sai();
    pthread_exit();
}
 
void homem_quer_entrar() {
    sem_wait(&homem);
    conta_homem += 1;
    if (conta_homem == 1) {
        sem_wait(&banheiro);
        printf("--------- Estado: Com homem ---------\n");
    }
    printf("Entrou homem, total: %d\n", conta_homem);
    sem_post(&homem);
}
 
void homem_sai() {
    sem_wait(&homem);
    conta_homem -= 1;
    printf("Saiu homem, total: %d\n", conta_homem);
    if (conta_homem == 0) {
        sem_post(&banheiro);
        printf("--------- Estado: Vazio ---------\n");
    }
    sem_post(&homem);
}
 
void homem_usa_banheiro() {
    usleep(rand() % 300000);
}
 
void adiciona_homem() {
    usleep(rand() % 400000);
    homem_quer_entrar();
    homem_usa_banheiro();
    homem_sai();
    pthread_exit();
}

Screenshots

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

banheiro.png

retornar

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