Java synchronized блокирует класс а не объект?

246
13 ноября 2017, 18:51

Добрый день, недавно читал Брюса Эккеля, и наткнулся на такую проблему: блок synchronized(Object) блокирует класс обьекта, е не сам обьект. К такому выводу я пришел после выполнения такого кода :

public class Main {
    public static void main(String[] args) {
        Sync s = new Sync();
        new Thread(new Runnable() {
            @Override
            public void run() {
                s.go();
            }
        }, "First").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                s.go();
            }
        }, "Second").start();
    }
}
class Sync {
    private Writer w1, w2;
    public Sync() {
        w1 = new Writer();
        w2 = new Writer();
    }
    public void go() {
        synchronized (w2) {
            w1.log(Thread.currentThread().getName() + "...1");
            //!Этот блок кода должен выполнятся паралельно во всех потоках, но выполняется последовательно.
            w2.log(Thread.currentThread().getName() + "...2");
            //Этот должен выполнятся последовательно, и он так и делает.
        }
    }
}
class Writer {
    public void log(Object obj) {
        for (int i = 0; i < 5; i++) {
            lgn(obj);
            try {
                TimeUnit.MILLISECONDS.sleep(750);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Почему при блокировки w2, у меня блокируется и w1? Это же разные обьекты?

В книге и во всех источниках говорится про блокировку в synchronized обьекта! Если я что-то не так сделал или чего-то не понимаю, то могли бы вы мне ответить почему и как?

Вывод

First...1
First...1
First...1
First...1
First...1
First...2
First...2
First...2
First...2
First...2
Second...1
Second...1
Second...1
Second...1
Second...1
Second...2
Second...2
Second...2
Second...2
Second...2

Ожидаемый вывод

First...1
Second...1
First...1
Second...1
First...1
Second...1
First...1
Second...1
First...1
Second...1
First...2
First...2
First...2
First...2
First...2
Second...2
Second...2
Second...2
Second...2
Second...2
Answer 1

Ваши комментарии в коде:

synchronized (w2) {
    w1.log(Thread.currentThread().getName() + "...1");
    //!Этот блок кода должен выполнятся паралельно во всех потоках, но выполняется последовательно.
    w2.log(Thread.currentThread().getName() + "...2");
    //Этот должен выполнятся последовательно, и он так и делает.
}

неверны.

Секция synchronized синхронизирует не объект, а участок кода. Это означает, что вся секция будет выполнена «одним куском», не прерываясь другой секцией с тем же синхронизирующим объектом (это как раз ваш случай).

Таким образом, сначала код в потоке "First" приходит к синхронизирующей секции и выполняет её полностью, и только потом поток "Second". (Ну или в обратном порядке, как повезёт.)

READ ALSO
BLE как отправлять данные &lt;20 бит

BLE как отправлять данные <20 бит

Собрал проект по данным исходникам переделал под свои нуждыИ возникла необходимость отправлять данные более 20 бит

262
Серверное приложение для всех ОС на Java

Серверное приложение для всех ОС на Java

ЗдравствуйтеРешил я улучшить свои навыки программирования и работы с базами данных

228
Помогите разобраться с реверсом байт

Помогите разобраться с реверсом байт

Задание: Реализуйте функцию Reverse, которая на вход принимает массив байт, выполняет битовый реверс каждого байта в массиве и выводит результат...

273