Почему нужно указывать объект? Ведь мы можем вообще не использовать этот объект в блоке.
Также чем отличается synchronized(this)
от synchronized(o)
(я знаю что значит this
, чем отличаются блоки с разными объектами)?
И наконец, почему мы можем использовать операции wait
, notify
и т.п. с Object o
, ведь он не поток?
Ключевое слово synchronized
является утверждением, которое в круглых скобках принимает выражение, возвращающее ссылку на объект. Поэтому его не нужно путать с методом, принимающим один параметр. И то, что используется в скобках - относится к самому утверждению, а не блоку кода, для которого это утверждение работает. Как и в любом другом блоке кода вы можете использовать ссылку на любой объект, если он доступен в области видимости, которая охватывает этот блок. Поэтому какую ссылку вы используете в утверждении synchronized
, не имеет отношения к тому, будете ли вы ее использовать в блоке кода или нет.
Вот, что по этому сказано в JLS:
Утверждение synchronized
получает блокировку взаимного исключения
(§17.1) от имени исполняющего потока, выполняет блок, а затем
освобождает блокировку. Пока исполняющий поток владеет блокировкой, ни
один другой поток не может получить блокировку.
SynchronizedStatement:
synchronized ( Expression ) Block
Тип выражения должен быть ссылочным типом, или возникает ошибка времени компиляции.
И наконец, методы wait()
, notify()
, и notifyAll()
принадлежат классу Object
. Поэтому вы можете использовать их в любом классе, вы также можете использовать ссылку на объект, для вызовов этих методов из этого объекта, имеющего эту ссылку. Так как впрочем все унаследованные методы доступны в классе без использования ссылки. Ссылка this
указывает на этот объект, поэтому ее указывать необязательно для вызовов наследуемых методов, в то время как для других объектов это необходимо. Поток тоже является объектом, потому, что создается из класса Thread
, поэтому если методы вызываются внутри класса, то принадлежат ему.
Также чем отличается synchronized(this) от synchronized(o)
ничем, все зависит от того что вы будете делать с объектом который по которому синхронизировались, возможно вы захотите передать его в метод или предоставить доступ к нему из вне.
И наконец, почему мы можем использовать операции wait, notify и т.п. с Object o, ведь он не поток?
Вот здесь у вас небольшой пробел в знаниях, вам необходимо почитать про понятие монитора. Вкратце у каждого объекта есть монитор, можете представлять его как флаг, когда вы пишете
synchronized(this) {...}
поток который заходит внуть этого блока захватывает монитор объекта this, таким образом другие потоки видят что монитор захвачен и не заходят внутрь.
Если рассматривать оператор
synchronized (ссылка_ на_ объект) {
// блок кода, который нужно синхронизировать
}
то здесь ссылка_ на_ объект
обозначает ссылку на синхронизируемый объект.
Блок оператора synchronized
гарантирует, что вызов метода, являющегося
членом того же класса, что и синхронизируемый объект, на который делается
ссылка_ на_ объект
, произойдет только тогда, когда текущий поток исполнения
успешно войдет в монитор данного объекта.
В синхронизируемом блоке можно не объявлять оператор synchronized
со ссылкой на объект тогда, когда вы точно используете метод, объявленный как synchronized
. Если вы не имеете исходника, чтобы пере-объявить этот метод, то используете оператор synchronized (ссылка_ на_ объект)
. Какой объект указывать - this
или o
- зависит от вашей программы. Если синхронизируется блок кода из текущего объекта, то он уже создан и ссылкой на него является this
. Если этот метод в другом объекте, то его и указываете. Как-то так...
Виртуальный выделенный сервер (VDS) становится отличным выбором
Смотрел JVM, наткнулся на аннотацию @HotSpotIntrinsicCandidate, довольно часто ее стал встречатьЧто она значит? Раньше ее не было
Java документация гласит, что джинерики работают с помощью механизма "стирания", те
Используя сторонние библиотеки, или нативные библиотеки Java, можно сделать цветной шрифт в терминале? Может что-то наподобие printf? И есть возможность...