Руководство по Java Core. Многопоточность. Взаимная блокировка.

Взаимная блокировка – это ситуация, при которой два или более потоков заблокированы навсегда, ожидая друг друга.

Для понимания того, как это работает на практике рассмотрим пример простого приложения.

Пример:

Класс DeadLockDemo


public class DeadLockDemo {
    public static final Object Lock1 = new Object();
    public static final Object Lock2 = new Object();


    public static void main(String[] args) {
        DeadThreadOne threadOne = new DeadThreadOne();
        DeadThreadTwo threadTwo = new DeadThreadTwo();

        threadOne.start();
        threadTwo.start();
    }

    private static class DeadThreadOne extends Thread {

        public void run() {
            synchronized (Lock1) {
                System.out.println("DeadThreadOne is holding LOCK 1...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("DeadThreadOne is waiting for Lock 2...");
                synchronized (Lock2) {
                    System.out.println("DeadThreadOne  is holding Lock 1 and Lock 2...");
                }
            }
        }


    }

    private static class DeadThreadTwo extends Thread {


        public void run() {
            synchronized (Lock2) {
                System.out.println("DeadThreadTwo is holding LOCK 2...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("DeadThreadOne is waiting for Lock 1...");
                synchronized (Lock1) {
                    System.out.println("DeadThreadOne  is holding Lock 1 and Lock 2...");
                }
            }
        }
    }
}

В результате работы этой программы, мы получим, примерно, следующий результат:


DeadThreadOne is holding LOCK 1...
DeadThreadTwo is holding LOCK 2...
DeadThreadOne is waiting for Lock 2...
DeadThreadOne is waiting for Lock 1...

Программа будет находиться в таком состоянии до момента её ручной остановки, потому что оба потока ожидают друг друга для того, чтобы продолжить свою работу.


Рассмотрим пример приложения, в котором показано, как избежать такой ситуации.
Пример:

Класс SolveDeadLock


public class SolveDeadLock {
    public static final Object Lock1 = new Object();
    public static final Object Lock2 = new Object();

    public static void main(String args[]) {

        ThreadOne threadOne = new ThreadOne();
        ThreadTwo threadTwo = new ThreadTwo();
        threadOne.start();
        threadTwo.start();
    }

    private static class ThreadOne extends Thread {
        public void run() {
            synchronized (Lock1) {
                System.out.println("ThreadOne is holding lock 1...");
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("ThreadOne is waiting for lock 2...");
                synchronized (Lock2) {
                    System.out.println("ThreadOne is holding lock 1 & 2...");
                }
            }
        }
    }

    private static class ThreadTwo extends Thread {
        public void run() {
            synchronized (Lock1) {
                System.out.println("ThreadTwo is holding lock 1...");
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("ThreadOne is waiting for lock 2......");
                synchronized (Lock2) {
                    System.out.println("ThreadTwo is holding lock 1 & 2...");
                }
            }
        }
    }
}

В результате работы этой программы, мы получим, примерно, следующий результат:


/*Some System Messages*/

ThreadOne is holding lock 1...
ThreadOne is waiting for lock 2...
ThreadOne is holding lock 1 & 2...
ThreadTwo is holding lock 1...
ThreadOne is waiting for lock 2......
ThreadTwo is holding lock 1 & 2...

В этом разделе мы изучили понятие взаимной блокировки и рассмотрели пример приложения с её реализацией и пример приложения, в котором показано, как избежать взаимной блокировки.