@Vadimayer

Пытаюсь понять суть захвата монитора, но почему не работает?

Есть тестовый код. Четыре потока работают с одним объектом. Два синхронизированных метода. Один статический, другой нет.
1. В моем понимании если один поток заходит в синхронизированный метод объекта то, он захватывает его монитор, следовательно другой поток и остальные должны ждать, но я не могу понять почему заходят оба потока.
2. И есть два статических синхронизированных метода, они относятся к классу, с этим вообще получается не ясно, если мы захватываем метод класса то, все объекты класса не могут быть захвачены остальными потоками. Что я не понимаю?

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

public class Test {
    static int vClass = 0;

    int object = 0;

    static synchronized void incrementClass() {
        vClass++;
    }

    synchronized void incrementObject() {
        object++;
    }
}

class Main {
    public static void main(String[] args) throws InterruptedException {

        Test test = new Test();

        Thread thread1 = new Thread(()-> {
            try {
                Test.incrementClass();
                System.out.println("зашли в поток класса " + Thread.currentThread().getName());
                //Имитация работы потока
                Thread.sleep(10000);
                Test.incrementClass();
                System.out.println("вышли из потока класса " + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        Thread thread2 = new Thread(()-> {
            Test.incrementClass();
            System.out.println("зашли в поток класса " + Thread.currentThread().getName());
            Test.incrementClass();
            Test.incrementClass();
            Test.incrementClass();
            System.out.println("вышли из потока класса " + Thread.currentThread().getName());
        });

        Thread thread3 = new Thread(()-> {
            try {
                test.incrementObject();
                System.out.println("зашли в поток объекта " + Thread.currentThread().getName());
                //Имитация работы потока
                Thread.sleep(10000);
                test.incrementObject();
                System.out.println("вышли из потока объекта " + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

        });

        Thread thread4 = new Thread(()-> {
            test.incrementObject();
            System.out.println("зашли в поток объекта " + Thread.currentThread().getName());
            test.incrementObject();
            System.out.println("вышли из потока объекта " + Thread.currentThread().getName());
        });



        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();
        Thread.sleep(500);

        System.out.println("Class " + Test.vClass);
        System.out.println("Object " + test.object);
        Thread.sleep(10500);
        System.out.println("Class " + Test.vClass);
        System.out.println("Object " + test.object);

    }
}


В результате:

зашли в поток объекта Thread-2
зашли в поток объекта Thread-3
зашли в поток класса Thread-0
зашли в поток класса Thread-1
вышли из потока объекта Thread-3
вышли из потока класса Thread-1
Class 5
Object 3
вышли из потока объекта Thread-2
вышли из потока класса Thread-0
Class 6
Object 4
  • Вопрос задан
  • 137 просмотров
Решения вопроса 1
xez
@xez Куратор тега Java
TL Junior Roo
У вас проблема в примере в том, что методы incrementClass() и incrementObject() выполняются практически мгновенно и потому кажется, что там нет блокировки.
Добавьте туда какой-нибудь Thread.sleep и сразу все встанет на свои места.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@jkotkot
режим сарказма
методы синхронизируются на разных объектах: один на this, а другой на Test.class
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
Bell Integrator Ульяновск
До 400 000 ₽
Bell Integrator Ижевск
До 400 000 ₽
Bell Integrator Хабаровск
До 400 000 ₽