Deadlock i Java är en del av multithreading. Deadlock kan uppstå i en situation när en tråd väntar på ett objektlås, som förvärvas av en annan tråd och andra tråden väntar på ett objektlås som förvärvas av den första tråden. Eftersom båda trådarna väntar på att varandra ska släppa låset kallas tillståndet dödläge.
Exempel på dödläge i Java
TestDeadlockExample1.java
set vs karta
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(); } }
Produktion:
Thread 1: locked resource 1 Thread 2: locked resource 2
Mer komplicerade dödlägen
Ett dödläge kan också innehålla fler än två trådar. Anledningen är att det kan vara svårt att upptäcka ett dödläge. Här är ett exempel där fyra trådar har låst sig:
Tråd 1 låser A, väntar på B
Trä 2 lås B, väntar på C
Trä 3 lås C, väntar på D
central css-knapp
Trä 4 lås D, väntar på A
Tråd 1 väntar på tråd 2, tråd 2 väntar på tråd 3, tråd 3 väntar på tråd 4 och tråd 4 väntar på tråd 1.
två till en multiplexor
Hur undviker man dödläge?
En lösning på ett problem finns i dess rötter. I dödläge är det mönstret att komma åt resurserna A och B, som är huvudfrågan. För att lösa problemet måste vi helt enkelt ordna om satserna där koden kommer åt delade resurser.
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; } } }
Produktion:
In block 1 In block 2
I ovanstående kod löser klass DeadlockSolved situationen med dödläge. Det kommer att hjälpa till att undvika dödlägen, och om de stöter på, att lösa dem.
Hur undviker man dödläge i Java?
Deadlocks kan inte lösas helt. Men vi kan undvika dem genom att följa grundläggande regler som nämns nedan: