logo

Deadlock в Java

Взаємоблокування в Java є частиною багатопоточності. Взаємоблокування може виникнути в ситуації, коли потік очікує блокування об’єкта, отриманого іншим потоком, а другий потік очікує блокування об’єкта, отриманого першим потоком. Оскільки обидва потоки чекають, поки один один звільнить блокування, умова називається взаємоблокуванням.

Deadlock в Java

Приклад Deadlock в 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(); } } 

Вихід:

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

Більш складні взаємоблокування

Взаємоблокування також може включати більше двох потоків. Причина в тому, що може бути важко виявити тупик. Ось приклад, у якому чотири потоки зайшли в тупик:

Потік 1 блокує A, очікує B

Нитка 2 замки B, очікує C

Протягніть 3 замки C, очікуйте на D

Натягніть 4 замки D, очікуйте A

Потік 1 очікує на потік 2, потік 2 очікує на потік 3, потік 3 очікує на потік 4, а потік 4 очікує на потік 1.

Як уникнути глухого кута?

Рішення проблеми знаходиться в її корінні. У тупиковій блокуві основним питанням є шаблон доступу до ресурсів A і B. Щоб вирішити проблему, нам доведеться просто змінити порядок операторів, у яких код звертається до спільних ресурсів.

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

Вихід:

 In block 1 In block 2 

У наведеному вище коді клас DeadlockSolved вирішує тупикову ситуацію. Це допоможе уникнути тупикових ситуацій, а якщо вони виникнуть, то й вирішити їх.

Як уникнути взаємоблокування в Java?

Взаємоблокування неможливо повністю вирішити. Але ми можемо уникнути їх, дотримуючись основних правил, наведених нижче:

    Уникайте вкладених блокувань: Ми повинні уникати блокування кількох потоків, це основна причина виникнення взаємоблокування. Зазвичай це відбувається, коли ви надаєте блокування кільком потокам.Уникайте непотрібних блокувань: Замки повинні бути надані важливим потокам. Надання блокувань непотрібним потокам, які спричиняють взаємоблокування.Використання Thread Join: Взаємоблокування зазвичай виникає, коли один потік чекає завершення іншого. У цьому випадку ми можемо використовувати приєднатися з максимальним часом, який займе потік.