Почему нужно указывать объект в блоке synchronised?

182
01 ноября 2018, 07:10

Почему нужно указывать объект? Ведь мы можем вообще не использовать этот объект в блоке.

Также чем отличается synchronized(this) от synchronized(o)(я знаю что значит this, чем отличаются блоки с разными объектами)?

И наконец, почему мы можем использовать операции wait, notify и т.п. с Object o, ведь он не поток?

Answer 1

Ключевое слово synchronized является утверждением, которое в круглых скобках принимает выражение, возвращающее ссылку на объект. Поэтому его не нужно путать с методом, принимающим один параметр. И то, что используется в скобках - относится к самому утверждению, а не блоку кода, для которого это утверждение работает. Как и в любом другом блоке кода вы можете использовать ссылку на любой объект, если он доступен в области видимости, которая охватывает этот блок. Поэтому какую ссылку вы используете в утверждении synchronized, не имеет отношения к тому, будете ли вы ее использовать в блоке кода или нет.

Вот, что по этому сказано в JLS:

Утверждение synchronized получает блокировку взаимного исключения (§17.1) от имени исполняющего потока, выполняет блок, а затем освобождает блокировку. Пока исполняющий поток владеет блокировкой, ни один другой поток не может получить блокировку.

SynchronizedStatement:
    synchronized ( Expression ) Block

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

И наконец, методы wait(), notify(), и notifyAll() принадлежат классу Object. Поэтому вы можете использовать их в любом классе, вы также можете использовать ссылку на объект, для вызовов этих методов из этого объекта, имеющего эту ссылку. Так как впрочем все унаследованные методы доступны в классе без использования ссылки. Ссылка this указывает на этот объект, поэтому ее указывать необязательно для вызовов наследуемых методов, в то время как для других объектов это необходимо. Поток тоже является объектом, потому, что создается из класса Thread, поэтому если методы вызываются внутри класса, то принадлежат ему.

Answer 2
Также чем отличается synchronized(this) от synchronized(o)

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

И наконец, почему мы можем использовать операции wait, notify и т.п. с Object o, ведь он не поток?

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

synchronized(this) {...}

поток который заходит внуть этого блока захватывает монитор объекта this, таким образом другие потоки видят что монитор захвачен и не заходят внутрь.

Answer 3

Если рассматривать оператор

synchronized (ссылка_ на_ объект) {
    // блок кода, который нужно синхронизировать
}

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

В синхронизируемом блоке можно не объявлять оператор synchronized со ссылкой на объект тогда, когда вы точно используете метод, объявленный как synchronized. Если вы не имеете исходника, чтобы пере-объявить этот метод, то используете оператор synchronized (ссылка_ на_ объект). Какой объект указывать - this или o - зависит от вашей программы. Если синхронизируется блок кода из текущего объекта, то он уже создан и ссылкой на него является this. Если этот метод в другом объекте, то его и указываете. Как-то так...

READ ALSO
Что значит аннотация @HotSpotIntrinsicCandidate?

Что значит аннотация @HotSpotIntrinsicCandidate?

Смотрел JVM, наткнулся на аннотацию @HotSpotIntrinsicCandidate, довольно часто ее стал встречатьЧто она значит? Раньше ее не было

179
Настройка конфигурации Hibernate в Spring

Настройка конфигурации Hibernate в Spring

Использую версии Spring 50

195
generic массивы и new T()

generic массивы и new T()

Java документация гласит, что джинерики работают с помощью механизма "стирания", те

218
Есть способы сделать цветной шрифт в терминале?

Есть способы сделать цветной шрифт в терминале?

Используя сторонние библиотеки, или нативные библиотеки Java, можно сделать цветной шрифт в терминале? Может что-то наподобие printf? И есть возможность...

161