.3. Problemas-comuns-de-concorrência
Starvation ocorre quando um processo nunca consegue ser executado devido a um scheduler não funcionar corretamente. Esse problema não é tratado por meio de primitivas e sim pela implementação de um scheduler que escala os processos conseguindo garantir execução a todos.
O livelock ocorre quando dois processos ficam alternando o controle da CPU entre si, assim ambos continuam vivos tentando entrar em execução e passando o controle sobre a CPU e assim nenhum dos dois executam. Esse problema também não é tratado já que depende de “sorte”.
O deadlock é similar ao livelock porém os dois processos ficam bloqueados esperando a liberação do recurso. As condições para que ocorra um deadlock são:
- Dois ou mais processos compartilham duas ou mais regiões críticas.
- Existe intersecção de regiões críticas.
- Formação de ciclo de espera.
- Ausência de preempção.
O deadlock pode ser resolvido por meio do algoritmo do avestruz, que pressupõe a raridade do deadlock e diz que basta apenas reiniciar a máquina.
Outro método é o timestamp de cada processo:
- wait-die: o processo mais velho espera e o mais novo morre
- wait-wound: o mais velho tenta executar e o mais novo espera.
The Dining Philosophers
Problema: há 5 filósofos numa mesa circular, cada qual com um garfo entre pares, ou seja, 5 garfos também.
![[Pasted image 20250512101132.png]]
Um filósofo pensa (libera os garfos) e come (usa os garfos). Precisamos identificar os garfos à esquerda e à direita do filósofo (cada um com seu ID próprio). Com:
int left(p) { return p;}
int right(p) { return p + 1) % n;}A solução é fazer cada um dos filósofos pegar um garfo inicial diferente. Ou seja, o filósofo 4 pega o garfo 0 (direita) enquanto o 0 tenta inicialmente pegar o garfo 0 (esquerda). Assim, se um deles conseguir pegar o garfo, o outro esperará, sem deadlocks possíveis.
Solução
# P = sem_wait()
# V = sem_post()
Philo[i=0 to n-2]{
while(true){
P(i);
P((i+1)%n);
eat();
V((i+1)%n);
V(i);
}
}
Philo[n-1]{
while(true){
think();
P(0);
P(n);
eat();
V(n);
V(0);
}
}Problema dos Fumantes (Smoker Problem)
O Problema dos Macacos (baboon crossing)
Suponha que haja macacos em ambas as margens de um rio e, de tempos em tempos, os macacos decidem passar para o outro lado à procura de comida. A passagem para a outra margem do rio é feita através de uma ponte de corda. Mais de um macaco pode atravessar a ponte ao mesmo tempo, mas isso só é possível se eles estiverem indo na mesma direção.
Implemente um programa que faça o controle da passagem de macacos pela ponte usando Semáforos. Para testar o sistema, crie 10 threads que representem os macacos, colocando inicialmente metade deles em cada margem do rio. Sempre que um macaco iniciar ou concluir a travessia, imprima uma mensagem na tela identificando o macaco.
Após testar o programa acima, crie agora uma nova verão do programa adicionando dois gorilas, um de cada lado do rio. Como os gorilas são muito pesados, eles só poderão atravessar a ponte sozinhos. Como os outros macacos têm medo dos gorilas, eles terão prioridade para fazer a travessia.
Problema do banheiro unissex
Declaração do Problema:
Um banheiro está sendo projetado para uso de homens e mulheres em um escritório, mas requer que as seguintes restrições sejam mantidas:
- Não pode haver homens e mulheres no banheiro ao mesmo tempo.
- Nunca deve haver mais de três funcionários no banheiro simultaneamente.
- Não deve haver inanição.
Process banheiro() {
P(Pessoa)
usaBanheiro()
}
process homem() {
while(true) {
P(Banheiro)
P(Mulher)
pessoa = "homem"
V(Pessoa)
V(Mulher)
V(Banheiro)
}
}
process mulher() {
while(true) {
P(Banheiro)
P(Homem)
pessoa = "mulher"
V(Pessoa)
V(Homem)
V(Banheiro)
}
}Problema do Barbeiro Dorminhoco
O problema se resume a um barbeiro que seria o processo e clientes que são outros processos, assim o corte de cabelo é determinado por meio do barbeiro que quando tem cliente realiza o corte e quando termina chama outro cliente ou dorme (entra no estado de bloqueado).
Barbeiro
Dorme se não tem cliente. Se tem cliente:
- Chama para cortar
- espera ele sentar
- faz o corte, avisa no final
- espera o cliente sair
Cliente
- Acorda o barbeiro se precisar
- Espera o barbeiro chamar
- Seguem instruções do Barbeiro
- saem após o corte
sem B = 1;
sem C = 1;
sem corte = 1;
sem saida = 1;
sem cad = 1;
Process Barber{
while(true){
P(C); // Espera Cliente
V(B); // Libera Barbeiro
P(cad); // Espera Cadeira
corta();
V(corte); // Libera Corte
P(saida); // Espera saída
}
}
Process Client[i=1 to N]{
while(true){
V(C); // Aumenta cliente
P(B); // Espera Barbeiro
V(cad); // Semaforo Cadeira
P(corte); // Espera corte
V(saida); // Espera Saida
}
}notas: processo é tratado como thread. cliente produz clientes, ou seja, quando chega um cliente o barbeiro é liberado. o cliente então espera ter barbeiros possíveis, se tiver, ele aumenta o numero de cadeira usadas. ai o barbeiro espera a cadeira aparecer, qnd tiver ele corta o cabelo e libera o semaforo de corte, que o cliente estava esperando. ai sim o barbeiro espera a saida do cliente

