Sistemas Operacionais Programação Concorrente Problemas clássicos Edson Moreno edson.moreno@pucrs.br http://www.inf.pucrs.br/~emoreno
Sumário Produtor / consumidor O jantar dos filósofos O barbeiro sonolento
Produtor / Consumidor Característica de execução Dois processos que compartilham um buffer de tamanho limitado O processo produtor: Produz um dado Insere no buffer Volta a gerar um dado O processo consumidor: Consome um dado do buffer (um por vez) O problema é Como garantir que o produtor não adicionará dados no buffer se este estiver cheio? Como garantir que o consumidor não vai remover dados de um buffer vazio?
Produtor / Consumidor Solução Para o processo produtor Entrar em Sleep ou descartar o dado se o buffer estiver cheio Quando o consumidro remover um item do buffer, este notifica o produtor Para o processo consumidor O mesmo pode ser feito no sentido inverso Na próxima inserção de dados pelo produtor, este notifica o consumidor Como implementar a solução? Via IPC, tal como semáforos. Construção deve ser cuidadosa Solução inadequada pode acarretar em deadlock Ambos processos aguardando notificação
Produtor / Consumidor Proposta de solução A partir do uso de semáforos Implementação de exclusão mútua Semáforos cheio e vazio cheio conta os espaços utilizados Se cheio igual a zero, então o consumidor deve ser bloqueado vazio conta os espaços não utilizados no buffer Se vazio igual a zero, então o produtor deve ser bloqueado
Produtor / Consumidor int buffer[tam_buffer]; sem_t cheio, vazio; void produtor(void *) { while (true) { item = produceitem(); sem_wait(&vazio); putitemintobuffer(item); sem_post(&cheio); } } int main(){ pthread_t prod, cons; sem_init(&cheio, 0,?); sem_init(&vazio, 0,?); void consumidor(void *) { while (true) { sem_wait(&cheio); item = removeitemfrombuffer(); sem_post(&vazio); consumeitem(item); } } pthread_create(&prod, NULL, produtor, NULL); pthread_create(&cons, NULL, consumidor, NULL); pthread_join(prod, NULL); pthread_join(cons, NULL); }
Produtor / Consumidor void produtor(void *) { while (true) { item = produceitem(); sem_wait(&vazio); putitemintobuffer(item); sem_post(&cheio); } } int buffer[tam_buffer]; sem_t cheio, vazio; int main(){ pthread_t prod, cons; sem_init(&cheio, 0, 0); sem_init(&vazio, 0, TAM_BUFFER); pthread_create(&prod, NULL, produtor, NULL); pthread_create(&cons, NULL, consumidor, NULL); pthread_join(prod, NULL); pthread_join(cons, NULL); } void consumidor(void *) { while (true) { sem_wait(&cheio); item = removeitemfrombuffer(); sem_post(&vazio); consumeitem(item); } }
Sumário Produtor / consumidor O jantar dos filósofos O barbeiro sonolento
O jantar dos filósofos
Jantar dos Filósofos Definção do problema Há cinco filósofos em torno de uma mesa. Um garfo é colocado entre cada filósofo. Cada filósofo deve, alternadamente, refletir e comer. Para que um filósofo coma, ele deve possuir dois garfos Os dois garfos devem ser aqueles logo a sua esquerda e a sua direita Para pegar um garfo Somente pode ser pego por um filósofo Somente pode ser pego não estiver em uso por nenhum outro filósofo Após comer, o filósofo deve liberar o garfo que utilizou Um filósofo pode segurar o garfo da sua direita ou o da sua esquerda assim que estiverem disponíveis Mas, só pode começar a comer quando ambos estiverem sob sua posse
Jantar dos Filósofos Solução 1 Solução funciona bem?
Jantar dos Filósofos Solução 1 Não, pois pode ocorrer deadlock Como?
Jantar dos Filósofos Solução 2 Proposta de solução E se após pegar pegarmos um garfo e não conseguimos pegar o outro devolvêssemos à mesa o primeiro garfo e esperássemos um tempo fixo?
Jantar dos Filósofos Solução 2 Proposta de solução E se após pegar pegarmos um garfo e não conseguimos pegar o outro devolvêssemos à mesa o primeiro garfo e esperássemos um tempo fixo? Solução é propensa a starvation
Jantar dos Filósofos Solução 3 Proposta de solução E se após pegar pegarmos um garfo e não conseguimos pegar o outro devolvêssemos à mesa o primeiro garfo e esperássemos um tempo, mas agora ALEATÓRIO?
Jantar dos Filósofos Solução 3 Proposta de solução E se após pegar pegarmos um garfo e não conseguimos pegar o outro devolvêssemos à mesa o primeiro garfo e esperássemos um tempo, mas agora ALEATÓRIO? Funcionaria algumas vezes, mas nem sempre Essas solução é usada em rede local Ethernet quando da colisão de pacotes; Assim sendo, a solução é válida para alguns caso, mas e se precisássemos de uma solução que funcionasse corretamente sempre?
Jantar dos Filósofos Solução 4 Proposta de solução Usando semáforos Após a estágio de pensamento tem-se Ou a captura dos recursos necessário para comer Ou o aguarde de uma notificação de que está apto a comer
Jantar dos Filósofos Solução 4
Jantar dos Filósofos Solução 4 Uma solução para o problema do jantar dos filósofos (parte 2)
Sumário Produtor / consumidor O jantar dos filósofos O barbeiro sonolento
O barbeiro sonolento
O barbeiro sonolento Descrição do problema A analogia de uma barbearia com um barbeiro. A barbearia possuir Uma cadeira para corte de cabelo Uma sala de espera com um número determinado de cadeiras Quando o barbeiro finaliza o corte de cabelo de um cliente Ele libera o cliente e vai até a sala de espera para ver se há algum cliente esperando Se há algum cliente esperando, ele trás consigo um dos clientes corta o seu cabelo Se não há clientes esperando então ele volta para a cadeira de corte para dormir Quando um cliente chega à barbearia O cliente olha o que o barbeiro está fazendo. Se o barbeiro estiver dormindo, ele o acorda e senta na cadeira. Se o barbeiro estiver trabalhando então o cliente vai para a sala de espera Se houver uma cadeira livre na sala de espera então ele senta e aguarda sua vez Se não houver cadeira livre na sala de espera então o cliente vai embora.
O barbeiro sonolento O problema Como programar o barbeiro e o(s) cliente(s) para não entrarem em uma situação de corrida Situação similar a ambientes que trabalham com fila Exemplo: Helpdesks para clientes cujo atendimento é enfileirado por um sistema centralizador de espera em uma fila de vagas limitadas
O Barbeiro Sonolento
O barbeiro sonolento Solução proposta Usa três semáforos Customer: Contabiliza e limita o número de clientes em espera Waiting: Essencialmente uma cópia de customer Barber: Contabiliza o número de barbeiros dormindo Mutex: usado para acesso à região crítica
O Barbeiro Sonolento