Как создать тупиковую ситуацию и решить ее в Java

Научитесь создавать взаимоблокировку в Java программным способом, с примером. Также научитесь обнаруживать взаимоблокировку и решать ситуацию взаимоблокировки в исходном коде.

Как правило, если программа не синхронизирована должным образом и системные ресурсы распределяются между потоками, всегда существует вероятность возникновения ситуации взаимоблокировки, когда несколько потоков ожидают доступа к ресурсам, удерживаемым друг другом.

1. Моделирование тупиковой ситуации

В Java взаимоблокировка — это ситуация, когда минимум два потока удерживают блокировку на каком-то другом ресурсе, и оба ждут, пока ресурс другого завершит свою задачу. И ни один из них не может снять блокировку с ресурса, который он удерживает.

сценарий тупика
Сценарий тупиковой ситуации

В приведенном выше случае у Потока-1 есть ресурс A, но ему нужен ресурс B для завершения обработки, и аналогично у Потока-2 есть ресурс B, но ему сначала нужен ресурс A.

public class ResolveDeadLockTest {public static void main(String[] args) {ResolveDeadLockTest test = new ResolveDeadLockTest();final A a = test.new A();final B b = test.new B();// Thread-1Runnable block1 = new Runnable() {public void run() {synchronized(a) {try {// Adding delay so that both threads can start trying to// lock resourcesThread.sleep(100);} catch(InterruptedException e) {e.printStackTrace();}// Thread-1 have A but need B alsosynchronized(b) {System.out.println("In block 1");}}}};// Thread-2Runnable block2 = new Runnable() {public void run() {synchronized(b) {// Thread-2 have B but need A alsosynchronized(a) {System.out.println("In block 2");}}}};new Thread(block1).start();new Thread(block2).start();}// Resource Aprivate class A {private int i = 10;public int getI() {return i;}public void setI(int i) {this.i = i;}}// Resource Bprivate class B {private int i = 20;public int getI() {return i;}public void setI(int i) {this.i = i;}}}

Выполнение приведенного выше кода приведет к взаимоблокировке по вполне очевидным причинам(объясненным выше). Теперь нам нужно решить эту проблему.

2. Как разрешить тупиковую ситуацию?

Я считаю, что решение любой проблемы заключается в определении корня проблемы. В нашем случае это шаблон доступа к ресурсам A и B, это главная проблема. Поэтому, чтобы решить ее, мы просто переупорядочим операторы, в которых код обращается к общим ресурсам.

// Thread-1Runnable block1 = new Runnable() {public void run() {synchronized(b) {try {// Adding delay so that both threads can start trying to// lock resourcesThread.sleep(100);} catch(InterruptedException e) {e.printStackTrace();}// Thread-1 have A but need B alsosynchronized(a) {System.out.println("In block 1");}}}};// Thread-2Runnable block2 = new Runnable() {public void run() {synchronized(b) {// Thread-2 have B but need A alsosynchronized(a) {System.out.println("In block 2");}}}};

Запустите снова выше класс, и вы не увидите никаких ситуаций типа взаимоблокировки. Надеюсь, это поможет вам избежать взаимоблокировок и, если они возникнут, разрешить их.

Прокрутить вверх