logo

Zakleszczenie w Javie

Zakleszczenie w Javie jest częścią wielowątkowości. Zakleszczenie może wystąpić w sytuacji, gdy wątek oczekuje na blokadę obiektu przejętą przez inny wątek, a drugi wątek oczekuje na blokadę obiektu przejętą przez pierwszy wątek. Ponieważ oba wątki czekają na siebie nawzajem, aby zwolnić blokadę, stan ten nazywa się zakleszczeniem.

Zakleszczenie w Javie

Przykład zakleszczenia w Javie

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(); } } 

Wyjście:

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

Bardziej skomplikowane zakleszczenia

Zakleszczenie może również obejmować więcej niż dwa wątki. Powodem jest to, że wykrycie zakleszczenia może być trudne. Oto przykład, w którym cztery wątki uległy zakleszczeniu:

Wątek 1 blokuje A, czeka na B

Wątek 2 blokuje B, czeka na C

Wątek 3 blokuje C, czeka na D

struny w c

Wątek 4 blokuje D, czeka na A

parseint Java

Wątek 1 czeka na wątek 2, wątek 2 czeka na wątek 3, wątek 3 czeka na wątek 4, a wątek 4 czeka na wątek 1.

Jak uniknąć impasu?

Rozwiązanie problemu można znaleźć u jego korzeni. W przypadku impasu głównym problemem jest sposób dostępu do zasobów A i B. Aby rozwiązać ten problem, będziemy musieli po prostu zmienić kolejność instrukcji, w których kod uzyskuje dostęp do współdzielonych zasobów.

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; } } } 

Wyjście:

 In block 1 In block 2 

W powyższym kodzie klasa DeadlockSolved rozwiązuje sytuację związaną z zakleszczeniem. Pomoże w uniknięciu zakleszczeń, a jeśli się pojawią, w ich rozwiązaniu.

Jak uniknąć zakleszczenia w Javie?

Zakleszczeń nie można całkowicie rozwiązać. Możemy ich jednak uniknąć, przestrzegając podstawowych zasad wymienionych poniżej:

    Unikaj zagnieżdżonych blokad: Musimy unikać blokowania wielu wątków, jest to główna przyczyna zakleszczenia. Zwykle dzieje się tak, gdy dajesz blokady wielu wątkom.Unikaj niepotrzebnych blokad: Zamki należy przypisać do ważnych wątków. Blokowanie niepotrzebnych wątków powodujących zakleszczenie.Korzystanie z łączenia wątków: Zakleszczenie zwykle ma miejsce, gdy jeden wątek czeka na zakończenie drugiego. W tym przypadku możemy skorzystać dołączyć z maksymalnym czasem trwania wątku.