Exemplo de Deadlock

6 respostas
F

Olá galera!

gostaria de saber se alguém aqui já usou, ou rodou algum exemplo/código
que gerasse algum deadlock em threads…

Valeus!!!

6 Respostas

R

Já vi exemplos… :wink:

F

sim … mas tem como vc postar pra gente discutir???

F

Exemplo Clássico:

public class Caixa {

    double saldoCaixa = 0.0;
    Cliente clienteDaVez = null;

    public synchronized void atender(Cliente c, int op, double v) {

        while (clienteDaVez != null) {
            wait();
        } //espera vez

        clienteDaVez = c;

        switch (op) {
        case -1:
            sacar(c, v);
            break;
        case 1:
            depositar(c, v);
            break;
        }
    }

    private synchronized void sacar(Cliente c, double valor) {

        while (saldoCaixa <= valor) {
            wait();
        } //espera saldo, vez

        if (valor > 0) {
            saldoCaixa -= valor;
            clienteDaVez = null;
            notifyAll();
        }
    }

    private synchronized void depositar(Cliente c, double valor) {
        if (valor > 0) {
            saldoCaixa += valor;
            clienteDaVez = null;
            notifyAll();
        }
    }
}

Onde está o deadlock?

Cenário 1:

Saldo do caixa: R$0.00

Cliente 1 (thread) é atendido (recebe acesso do caixa),
deposita R$100.00 e libera o caixa

Cliente 2 (thread) é atendido (recebe o acesso do caixa),
saca R$50.00 e libera o caixa

Cenário 2: cliente 2 chega antes de cliente 1

Saldo do caixa: R$0.00

Cliente 2 é atendido (recebe acesso do caixa), tenta sacar
R$50.00 mas não há saldo. Cliente 2 espera haver saldo.

Cliente 1 tenta ser atendido (quer depositar R$100.00)
mas não é sua vez na fila. Cliente 1 espera sua vez.

DEADLOCK!

Estou vendo a cadeira de SO na faculdade e achei esse um exemplo bastante interessante e de facil entendimento !!!

:?: COMO RESOLVER? :twisted:

VAMU DISCUTIR!!! :razz:

R

Fábio,

Pelo que entendo, deadlock acontece quando segmentos estão bloqueados aguardando a liberação de bloqueios uns dos outros.

No seu exemplo apenas um segmento detém o bloqueio e não fica aguardando que outro segmento o libere. :oops:

À seguir, um exemplo que adaptei do livro da Kathy:

package teste;

public class Teste {
  public static void main(String[] args) {
    Recurso rc = new Recurso();
    Thread01 t1 = new Thread01(rc);
    Thread02 t2 = new Thread02(rc);    
    
    t1.start(); 
    t2.start(); 
  }
}


class Thread01 extends Thread {
  private Recurso rc;
  
  public Thread01(Recurso rc) {
    this.rc = rc;
  }
  
  public void run() {
    rc.setValores(100, 200);
  }
}


class Thread02 extends Thread {
  private Recurso rc;
  
  public Thread02(Recurso rc) {
    this.rc = rc;
  }
  
  public void run() {
    rc.getValores();
  }
}


class Recurso {
  private Dispositivo ds1 = new Dispositivo();
  private Dispositivo ds2 = new Dispositivo();
  
  public void setValores(int x, int y) {
    synchronized (ds1) {
      ds1.setValor(x);
      
      try {
        Thread.sleep(1000);
      }
      catch (InterruptedException e ) {}
      
      synchronized (ds2) {
        ds2.setValor(y);
      }
    }
  }
  
  public void getValores() {
    synchronized (ds2) {
      System.out.println("O valor de ds2 é " + ds2.getValor());
      
      try {
        Thread.sleep(1000);
      }
      catch (InterruptedException e) {}
      
      synchronized (ds1) {
        System.out.println("O valor de ds1 é " + ds1.getValor());
      }
    }
  }
}


class Dispositivo {
  private int valor;
  
  public void setValor(int x) {
    valor = x;
  }
  
  public int getValor() {
    return valor;
  }
}
F

fabiostb manda ai o metodo main … pra gente ve se ocorre Deadlock.
No exemplo q o robson mandou … o deadlock rolou fica travado o processamento …

Seria como se elas entrassem em disturbio hehehehe
uma esperando a outra … soh q ninguem eh capaz de liberar primeiro …

F

cara segue ai o codigo q eu ja testei, esse metodo main foi eu quem fez seguindo a ideia dos cenarios, como eu citei anteriormente, porem agora o nobre amigo Robson me deixou na duvida se esse meu exemplo é um deadlock. Nesse exemplo coloquei uma thread startando logo em seguida da outra, acho q isso n garante 100% q vai haver deadlock, pois as thread podem, por sorte do azar, começar no sentido inverso por algum motivo/decisão do escalonador.

Para ter mais segurança q vai ter deadlock é só por os dois clientes dentro de um laço, tentando sacar e depositar infinitamente, assim q um q ta tentando sacar tentar tirar um valor maior do q tem na conta a parada entra em deadlock e o troxo todo morre, pois para o JOAO poder depositar a grana, a rasgada da MARIA tem q deixa o atendimento, e isso num ocorre nunca (nesse caso) pq MARIA foi dormir e deixou o JOAO na fila pra sempre. DESGRACADA :oops: - acho q é por ai

OBS.: FIZ ALGUNS AJUSTE, COLOCANDO UMAS IMPRESSÕES NO CONSOLE SOBRE O Q EXATAMENTE JOAO E MARIA ESTAO FAZENDO, PRA FACILITAR A ANALISE, VISTO Q É FODA, ou talvez impossivel, DEPURAR THREADs

public class Teste2 {

    double saldoCaixa = 0.0;
    Cliente clienteDaVez = null;

    public synchronized void atender(Cliente c, int op, double v) {
        System.out.println(c.getNome() + " está tentando ser atendido(a)");
        while (clienteDaVez != null) {
            try {
                System.out.println(c.getNome() + " NÃO foi atendido(a). FOI DORMIR");
                wait();
            } catch (InterruptedException e) {

            }
        } //espera vez
        System.out.println(c.getNome() + " foi atendido(a)");
        clienteDaVez = c;

        switch (op) {
        case -1:
            sacar(c, v);
            break;
        case 1:
            depositar(c, v);
            break;
        }
    }

    private synchronized void sacar(Cliente c, double valor) {
        System.out.println(c.getNome() + " está tentando sacar");
        while (saldoCaixa <= valor) {
            try {
                System.out.println(c.getNome() + " não conseguiu sacar. SALDO INSUFICIENTE!. FOI DORMIR");
                wait();
            } catch (InterruptedException e) {

            }
        } //espera saldo, vez

        if (valor > 0) {
            saldoCaixa -= valor;
            clienteDaVez = null;
            notifyAll();
        }
    }

    private synchronized void depositar(Cliente c, double valor) {
        System.out.println(c.getNome() + " está tentando depositar");
        if (valor > 0) {
            System.out.println(c.getNome() + " conseguiu depositar");
            saldoCaixa += valor;
            clienteDaVez = null;
            notifyAll();
        }
    }

    public static void main(String args[]) {
        final Teste2 caixa = new Teste2();

        Cliente cliente2 = new Cliente("Maria") {
            public void run() {
                caixa.atender(this, -1, 50);
            }
        };
        
        cliente2.start();
        
        Cliente cliente1 = new Cliente("João") {
            public void run() {
                caixa.atender(this, 1, 100);
            }
        };
        
        cliente1.start();
    }
}


class Cliente extends Thread {
    private String nome;
    Cliente(String nome) {
        this.nome = nome;
    }
    public String getNome() {
        return nome;
    }
}

Esse lance de concorrencia, condicao de corrida, deadlock, semaforos é um assunto muito rico e se quisermos complicar n teremos trabalho :roll: ! tudo feito com threads tem de ser feito com muito cuidado e analise :???: [/code]

Criado 28 de março de 2005
Ultima resposta 29 de mar. de 2005
Respostas 6
Participantes 3