Deadlock i Java er en del af multithreading. Deadlock kan opstå i en situation, hvor en tråd venter på en objektlås, som er erhvervet af en anden tråd, og anden tråd venter på en objektlås, der er erhvervet af den første tråd. Da begge tråde venter på, at hinanden frigiver låsen, kaldes tilstanden deadlock.
Eksempel på dødvande i 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(); } }
Produktion:
Thread 1: locked resource 1 Thread 2: locked resource 2
Mere komplicerede dødvande
En dødvande kan også omfatte mere end to tråde. Årsagen er, at det kan være svært at opdage en dødvande. Her er et eksempel, hvor fire tråde er gået i stå:
Tråd 1 låser A, venter på B
Tråd 2 låse B, venter på C
Tråd 3 låse C, venter på D
Tråd 4 låse D, venter på A
Tråd 1 venter på tråd 2, tråd 2 venter på tråd 3, tråd 3 venter på tråd 4, og tråd 4 venter på tråd 1.
Hvordan undgår man dødvande?
En løsning på et problem findes i dets rødder. I dødvande er det mønsteret for adgang til ressourcerne A og B, der er hovedproblemet. For at løse problemet bliver vi nødt til blot at omarrangere sætningerne, hvor koden har adgang til delte ressourcer.
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 ovenstående kode løser klasse DeadlockSolved den deadlock slags situation. Det vil hjælpe med at undgå dødvande, og hvis de støder på, med at løse dem.
Hvordan undgår man dødvande i Java?
Deadlocks kan ikke løses fuldstændigt. Men vi kan undgå dem ved at følge de grundlæggende regler nævnt nedenfor: