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

100
03 февраля 2021, 08:30
public class test implements Runnable {
    A a = new A();
    B b = new B();
    test() {
        Thread.currentThread().setName("Главный поток");
        Thread t = new Thread(this, "Соперничающий поток");
        t.start();
        a.foo(b); // получить блокировку для объекта a в этом потоке исполнения
        System.out.println("Назад в главный поток");
    }
    public void run() {
        b.bar(a); // получить блокировку для объекта b в другом потоке исполнения
        System.out.println("Назад в другой поток");
    }
    public static void main(String[] args) {
        new test();
    }
}
class A {
    synchronized void foo(B b) {
        String name = Thread.currentThread().getName();
        System.out.println(name + " вошел в метод A.foo()");
        try {
            Thread.sleep(1000);
        } catch (Exception e) {
            System.out.println("class A is break");
        }
        System.out.println(name + " пытается вызвать метод B.last()");
        b.last();
    }
    synchronized void last() {
        System.out.println("В методе A.last()");
    }
}
    class B {
    synchronized void bar(A a) {
        String name = Thread.currentThread().getName();
        System.out.println(name + " вошел в метод B.bar()");
        try {
            Thread.sleep(1000);
        } catch (Exception e) {
            System.out.println("class B is break");
        }
        System.out.println(name + " пытается вызвать метод A.last()");
        a.last();
    }
    synchronized void last() {
        System.out.println("В методе A.last()");
    }
}

Главный поток входит в монитор объекта A. Соперничающий входит в монитор объекта B. Почему когда поток исполнения в объекте A пытается вызвать синхронизированный метод для объекта B он блокируется? Почему когда поток исполнения в объекте B пытается вызвать синхронизированный метод для объекта A, то он будет ждать вечно? Я так понял монитор распространяется на весь объект что-ли, а не на метод в объекте?

Answer 1

Да, монитор распространяется на весь объект. Запись

class A {
    synchronized void aVoid() {
    }
}

аналогична записи

class A {
     void aVoid() {
         synchronized(this) {
         }
     }
}

То есть, при выполнении синхронизированного метода или блока, синхронизированного с текущим объектом, весь объект блокируется, и у него нельзя вызвать никакие другие синхронизированные методы. Такая взаимная блокировка, как в вашем примере, называется Deadlock.

READ ALSO
HQL getSingleResult с подзапросом

HQL getSingleResult с подзапросом

Пытаюсь написать запрос на hql, который вернет одну цифру методом getSingleResult(), все вполне сносно работало до тех пор, пока не появилась нужда...

120
Тестирование на java selenium

Тестирование на java selenium

Задача: залогиниться на сайт https://accountsgoogle

140
Что, если опускать аргументы (типы) для методов-дженериков?

Что, если опускать аргументы (типы) для методов-дженериков?

Я знаю, что если не указывать аргументы (вообще без угловых скобок) для классов-дженериков, то аргументами будет считаться тип Objcect, и что так...

125
TreeSet метод first() java

TreeSet метод first() java

Подскажите как можно реализовать метод который должен возвращать самый малый элемент

97