Zastoj v Javi je del večnitnosti. Do zastoja lahko pride v primeru, ko nit čaka na zaklepanje objekta, ki ga pridobi druga nit, druga nit pa čaka na zaklepanje objekta, ki ga pridobi prva nit. Ker obe niti čakata druga na drugo, da sprostita zaklepanje, se stanje imenuje zastoj.
Primer zastoja v Javi
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(); } }
Izhod:
Thread 1: locked resource 1 Thread 2: locked resource 2
Bolj zapleteni zastoji
Zastoj lahko vključuje tudi več kot dve niti. Razlog je v tem, da je težko odkriti zastoj. Tukaj je primer, v katerem so štiri niti zastale:
Nit 1 zaklene A, čaka na B
Nit 2 zaklene B, čaka na C
Niti 3 ključavnice C, čaka na D
Nit 4 zaklene D, čaka na A
Nit 1 čaka na nit 2, nit 2 čaka na nit 3, nit 3 čaka na nit 4 in nit 4 čaka na nit 1.
Kako se izogniti zastoju?
Rešitev za problem se najde v njegovih koreninah. V zastoju je glavni problem vzorec dostopa do virov A in B. Da bi rešili težavo, bomo morali preprosto preurediti stavke, kjer koda dostopa do skupnih virov.
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; } } }
Izhod:
In block 1 In block 2
V zgornji kodi razred DeadlockSolved rešuje vrsto situacije zastoja. Pomagal bo pri izogibanju zastojem in, če do njih pride, pri njihovem reševanju.
Kako se izogniti zastoju v Javi?
Zastojev ni mogoče popolnoma rešiti. Lahko pa se jim izognemo, če upoštevamo spodaj navedena osnovna pravila: