Java — Самоучитель

  • 15. Java — Массивы
  • 16. Java — Дата и время
  • 17. Java — Регулярные выражения
  • 18. Java — Методы
  • 21. Java — Вложенные и внутренние классы
  • 22. Java — Наследование
  • 23. Java — Переопределение
  • 24. Java — Полиморфизм
  • 25. Java — Абстракция
  • 26. Java — Инкапсуляция
  • 27. Java — Интерфейсы
  • 28. Java — Пакеты
  • 31. Java — Дженерики
  • 32. Java — Сериализация
  • 34. Java — Отправка Email
  • 36. Java — Основы работы с апплетами
  • 37. Java — Javadoc
  • 35.4. Java — Взаимная блокировка потоков

    Взаимная блокировка описывает ситуацию, когда два или более потока блокируются, ожидая друг друга. Взаимная блокировка возникает, когда нескольким потокам нужны одинаковые блокировки, но они получают их в разном порядке. Многопоточная программа Java может пострадать от состояния взаимоблокировки, поскольку ключевое слово synchronized заставляет выполняющийся поток блокироваться в ожидании блокировки или монитора, связанного с указанным объектом. Вот пример.

    Пример

    public class TestThread {
       public static Object Lock1 = new Object();
       public static Object Lock2 = new Object();
       
       public static void main(String args[]) {
          ThreadDemo1 T1 = new ThreadDemo1();
          ThreadDemo2 T2 = new ThreadDemo2();
          T1.start();
          T2.start();
       }
       
       private static class ThreadDemo1 extends Thread {
          public void run() {
             synchronized (Lock1) {
                System.out.println("Поток 1: Удерживает блокировку 1...");
                
                try { Thread.sleep(10); }
                catch (InterruptedException e) {}
                System.out.println("Поток 1: Ожидает блокировку 2...");
                
                synchronized (Lock2) {
                   System.out.println("Поток 1: Удерживает блокировку 1 и 2...");
                }
             }
          }
       }
       private static class ThreadDemo2 extends Thread {
          public void run() {
             synchronized (Lock2) {
                System.out.println("Поток 2: Удерживает блокировку 2...");
                
                try { Thread.sleep(10); }
                catch (InterruptedException e) {}
                System.out.println("Поток 2: Ожидает блокировку 1...");
                
                synchronized (Lock1) {
                   System.out.println("Поток 2: Удерживает блокировку 1 и 2...");
                }
             }
          }
       } 
    }
    

    Когда вы компилируете и выполняете вышеуказанную программу, вы обнаруживаете взаимную блокировку, и получаете следующий вывод программы:

    Поток 1: Удерживает блокировку 1 ...
    Поток 2: Удерживает блокировку 2 ...
    Поток 1: Ожидает блокировку 2 ...
    Поток 2: Ожидает блокировку 1 ...
    

    Вышеупомянутая программа зависнет навсегда, потому что ни один из потоков не может продолжить и ожидает пока другой поток освободит блокировку, поэтому вы можете выйти из программы, нажав CTRL + C.

    Пример решения взаимной блокировки

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

    Пример

    public class TestThread {
       public static Object Lock1 = new Object();
       public static Object Lock2 = new Object();
       
       public static void main(String args[]) {
          ThreadDemo1 T1 = new ThreadDemo1();
          ThreadDemo2 T2 = new ThreadDemo2();
          T1.start();
          T2.start();
       }
       
       private static class ThreadDemo1 extends Thread {
          public void run() {
             synchronized (Lock1) {
                System.out.println("Поток 1: Удерживает блокировку 1...");
                
                try {
                   Thread.sleep(10);
                } catch (InterruptedException e) {}
                System.out.println("Поток 2: Ожидает блокировку 2...");
                
                synchronized (Lock2) {
                   System.out.println("Поток 1: Удерживает блокировку 1 и 2...");
                }
             }
          }
       }
       private static class ThreadDemo2 extends Thread {
          public void run() {
             synchronized (Lock1) {
                System.out.println("Поток 2: Удерживает блокировку 1...");
               
                try {
                   Thread.sleep(10);
                } catch (InterruptedException e) {}
                System.out.println("Поток 2: Ожидает блокировку 2...");
                
                synchronized (Lock2) {
                   System.out.println("Поток 2: Удерживает блокировку 1 и 2...");
                }
             }
          }
       } 
    }
    

    Таким образом, простое изменение порядка блокировок предотвращает взаимную блокировку и завершается со следующим результатом:

    Поток 1: Удерживает блокировку 1 ...
    Поток 1: Ожидает блокировку 2 ...
    Поток 1: Удерживает блокировку 1 и 2 ...
    Поток 2: Удерживает блокировку 1 ...
    Поток 2: Ожидает блокировку 2 ...
    Поток 2: Удерживает блокировку 1 и 2 ...
    

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

    Поделитесь:

    О сайте

    Все материалы сайта proglang.su являются результатом труда его авторов. Копирование материалов в некоммерческих целях без указания источника в виде прямой ссылки на сайт proglang.su запрещено. Использование материалов в коммерческих целях разрешено только с письменного согласия автора. Нарушение авторских прав преследуется по закону. Мы это делаем, чтобы защитить плоды своих трудов от воровства. © 2014-2019

    Присоединяйтесь


    Обратная связь