logo

Impasse em Java

O impasse em Java faz parte do multithreading. O deadlock pode ocorrer em uma situação em que um thread está aguardando um bloqueio de objeto, que é adquirido por outro thread, e o segundo thread está aguardando um bloqueio de objeto, adquirido pelo primeiro thread. Como ambos os threads estão esperando um pelo outro para liberar o bloqueio, a condição é chamada de deadlock.

Impasse em Java

Exemplo de impasse em Java

TestDeadlockExample1.java

 public class TestDeadlockExample1 { public static void main(String[] args) { final String resource1 = 'ratan jaiswal'; final String resource2 = 'vimal jaiswal'; // t1 tries to lock resource1 then resource2 Thread t1 = new Thread() { public void run() { synchronized (resource1) { System.out.println('Thread 1: locked resource 1'); try { Thread.sleep(100);} catch (Exception e) {} synchronized (resource2) { System.out.println('Thread 1: locked resource 2'); } } } }; // t2 tries to lock resource2 then resource1 Thread t2 = new Thread() { public void run() { synchronized (resource2) { System.out.println('Thread 2: locked resource 2'); try { Thread.sleep(100);} catch (Exception e) {} synchronized (resource1) { System.out.println('Thread 2: locked resource 1'); } } } }; t1.start(); t2.start(); } } 

Saída:

 Thread 1: locked resource 1 Thread 2: locked resource 2 

Impasses mais complicados

Um deadlock também pode incluir mais de dois threads. A razão é que pode ser difícil detectar um impasse. Aqui está um exemplo em que quatro threads entraram em conflito:

Thread 1 bloqueia A, espera por B

Thread 2 bloqueia B, espera por C

Thread 3 bloqueia C, espera por D

Thread 4 bloqueia D, espera por A

O thread 1 espera pelo thread 2, o thread 2 espera pelo thread 3, o thread 3 espera pelo thread 4 e o thread 4 espera pelo thread 1.

Como evitar o impasse?

A solução para um problema é encontrada em suas raízes. No impasse é o padrão de acesso aos recursos A e B, que é a questão principal. Para resolver o problema teremos que simplesmente reordenar as instruções onde o código está acessando recursos compartilhados.

DeadlockSolved.java

 public class DeadlockSolved { public static void main(String ar[]) { DeadlockSolved test = new DeadlockSolved(); final resource1 a = test.new resource1(); final resource2 b = test.new resource2(); // Thread-1 Runnable b1 = new Runnable() { public void run() { synchronized (b) { try { /* Adding delay so that both threads can start trying to lock resources */ Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } // Thread-1 have resource1 but need resource2 also synchronized (a) { System.out.println('In block 1'); } } } }; // Thread-2 Runnable b2 = new Runnable() { public void run() { synchronized (b) { // Thread-2 have resource2 but need resource1 also synchronized (a) { System.out.println('In block 2'); } } } }; new Thread(b1).start(); new Thread(b2).start(); } // resource1 private class resource1 { private int i = 10; public int getI() { return i; } public void setI(int i) { this.i = i; } } // resource2 private class resource2 { private int i = 20; public int getI() { return i; } public void setI(int i) { this.i = i; } } } 

Saída:

 In block 1 In block 2 

No código acima, a classe DeadlockSolved resolve o tipo de situação de deadlock. Ajudará a evitar impasses e, se encontrados, a resolvê-los.

Como evitar impasses em Java?

Os impasses não podem ser completamente resolvidos. Mas podemos evitá-los seguindo as regras básicas mencionadas abaixo:

    Evite bloqueios aninhados: Devemos evitar bloquear vários threads, esse é o principal motivo para uma condição de deadlock. Normalmente acontece quando você bloqueia vários threads.Evite bloqueios desnecessários: Os bloqueios devem ser dados aos threads importantes. Dando bloqueios aos threads desnecessários que causam a condição de deadlock.Usando junção de thread: um deadlock geralmente acontece quando um thread está aguardando o término do outro. Neste caso, podemos usar juntar com o tempo máximo que um thread levará.