Um problema clássico de sincronização é o do
"Jantar dos Filósofos", que foi proposto em 1965 pelo matemático por Dijkstra (1965) e
apresenta a seguinte caracterização:
Cinco filósofos estão
sentados ao redor de uma mesa circular para o jantar. Cada filósofo possui um prato para comer. Os filósofos dispõem de hashis e cada um precisa
de 2 hashis para comer. Entre cada par de pratos existe apenas um hashi,
ou em termos de concorrência, hashis precisam ser compartilhados de forma
sincronizada.
Os filósofos comem e pensam, alternadamente. Eles
não se atém a apenas uma dastarefas. Além disso, quando comem, pegam apenas um hashi
por vez: Se conseguir pegar os dois come por alguns instantes e depois larga os
hashis.
O problema é coordenar o uso dos hashis de maneira que nenhum filósofo fique comfome. Esse problema exemplifica muito bem muitas soluções e muitos problemas encontrados na programação concorrente.
Pode facilmente
ocorrer o deadlock se cada filósofo pegar o seu hashi da esquerda e se recusar a liberá-lo até
ter comido. Pode ocorrer a inanição se dois filósofos conspirarem contra um terceiro.
Assim, uma implementação desse problema deve tratar o deadlock e usar ummecanismo de state para controlar o acesso a região crítica, que é o uso do hashi.
Em termos da programação, isso significa que teremos 5 objetos (filósofos) e 5 objetos compartilhados (os talheres). Nesse termo que entra o conceito de Thread pois para o compartilhamento múltiplos de objetos é necessária uma programação simultânea, ou seja, todos filósofos "vivos" e todos talheres manipuláveis.
Precisamos desenvolver as classes: Filosofo ( Representa os filósofos em si, e o que eles são capazes de fazer na mesa ), Semaforo ( Define uma propriedade para mostrar aos outro filósofos 0 se estiver livre para uso, 1 se estiver ocupado para uso ), Grade ( Que cria o ambiente e exibe na tela ) e JantarDosFilosofos ( Nosso método principal que implementa nossa Grade ). O nome do pacote é JANTARDOSFILOSOFOS.
package threads;
ResponderExcluirpublic class Controle{
protected int contador;// Criação de um contador protegido para esta classe
public Controle (){// Método construtor da classe que não recebe nenhum valor
this.contador = 0;
}
public Controle (int valor){// Método construtor da classe que recebe um valor para setar no contador
this.contador = valor;
}
// Método de sincronização da classe onde será decrescido o contador
public synchronized void decrementar (){
// Enquanto o contador for igual a 0, ele aguarda e trata a exceção
while (this.contador == 0){
try{
// Espera uma nova solicitação
wait();
}
catch (InterruptedException ex){
// Exibe uma mensagem de controle de erro
System.out.println("ERROR>" + ex.getMessage());
}
}
// Caso tenha saído do while acima, então decrementa o
// contador da classe
this.contador--;
}
// Método de sincronização da classe onde será incrementado o contador
public synchronized void incrementar (){
// Incrementa o contador da classe
this.contador++;
// Notifica que a solicitação já foi executada
notify();
}
}
package threads;
ResponderExcluirimport javax.swing.JFrame;
public class Main extends JFrame{
public Main (){
add(new Restaurante());
setTitle("Jantar dos Filósofos");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(410, 410);
setLocationRelativeTo(null);
setVisible(true);
setResizable(false);
}
public static void main(String[] args){
new Main();
}
}