Você está na página 1de 26

Sistemas Operacionais

Programação Concorrente
Problemas clássicos
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
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
void produtor(void *) { int buffer[TAM_BUFFER]; void consumidor(void *) {
while (true) { sem_t cheio, vazio; while (true) {
item = produceItem(); sem_wait(&cheio);
sem_wait(&vazio); item = removeItemFromBuffer();
putItemIntoBuffer(item); sem_post(&vazio);
sem_post(&cheio); consumeItem(item);
} }
} }
int
main()
{
pthread_t prod,
cons;
sem_init(&cheio, 0, ?); NULL, produtor, NULL);
pthread_create(&prod,
sem_init(&vazio,
pthread_create(&cons, NULL, consumidor, NULL);
0, ?);
pthread_join(prod, NULL);
pthread_join(cons,
NULL);
Produtor /
Consumidor
void produtor(void *) { int buffer[TAM_BUFFER]; void consumidor(void *) {
while (true) { sem_t cheio, vazio; while (true) {
item = produceItem(); sem_wait(&cheio);
sem_wait(&vazio); item = removeItemFromBuffer();
putItemIntoBuffer(item); sem_post(&vazio);
sem_post(&cheio); consumeItem(item);
} }
} }
int
main()
{
pthread_t prod,0, TAM_BUFFER);
sem_init(&vazio,
cons;
sem_init(&cheio, 0, 0); NULL, produtor, NULL);
pthread_create(&prod,
pthread_create(&cons, NULL, consumidor, NULL);

pthread_join(prod, NULL);
pthread_join(cons,
NULL);
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
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
 Descrição do
sonolento
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
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

Você também pode gostar