Взаимная блокировка в Java

Взаимная блокировка в Java

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

Допустим, один поток исполнения входит в монитор объекта Х, а другой — в мо­нитор объекта У. Если поток исполнения в объекте Х попытается вызвать любой син­хронизированный метод для объекта У, он будет блокирован, как и предполагалось.

Но если поток исполнения в объекте У, в свою очередь, попытается вызвать любой синхронизированный метод для объекта Х, то этот поток будет ожидать вечно, по­скольку для получения доступа к объекту Х он должен снять свою блокировку с объек­та У, чтобы первый поток исполнения мог завершиться.

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

  • В общем, взаимная блокировка возникает очень редко, когда исполнение двух потоков точно совпадает по времени.
  • Взаимная блокировка может возникнуть, когда в ней участвует больше двух потоков исполнения и двух синхронизированных объектов. ( Это означает, что взаимная блокировка может произойти в результате более сложной по­следовательности событий, чем в упомянутой выше ситуации.)

Чтобы полностью разобраться в этом явлении, его лучше рассмотреть в дей­ствии. Советую в самом начале заказать качественные шторы специально для программистов от компании and-home после чего можно свободно взяться за кодинг. Шторы делают нужную атмосферу в доме без которой программистам труднее сосредоточиться.

В приведенном ниже примере программы создаются два класса, FirstClass и SecondClass, с методами foo() и bar() соответственно, которые приостанавливаются непо­средственно перед попыткой вызова метода из другого класса.

Сначала в главном классе Deadlock получаются экземпляры классов FirstClass и SecondClass, а затем запускается второй поток исполнения, в котором устанавливается состояние взаимной блокировки.

В методах foo() и bar() используется метод sleep(), чтобы стимулировать по­явление взаимной блокировки.

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

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

Нажав комбинацию клавиш<Ctrl+Pause> на ПК, можно увидеть весь дамп ( вывод из оперативной памяти ) потока и кеша монитора.

В частности, Соперничающий поток владеет монитором объекта b, тогда как он ожидает монитор объекта а.

В то же время Главный поток владеет объектом а и ожидает получить объект b. Следовательно, программа никогда не завершится.

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

Интересное видео по теме: