Главное, что обычный блок synchronized
использует в качестве монитора вмещающий объект, другими словами, это эквивалентно использованию synchronized(this) { }
.Проблема заключается в области видимости / видимости: любой класс, внешний по отношению к вашему классу, может выбрать синхронизацию в одном и том же экземпляре и вмешаться в вашу логику синхронизации.При использовании ссылки private final
в качестве монитора это больше невозможно (при условии отсутствия отраженных махинаций).
Это сформулировано в Параллелизм Java на практике следующим образом (стр. 61, раздел 4.2)..1):
Существуют преимущества использования объекта частной блокировки вместо внутренней блокировки объекта (или любой другой общедоступной блокировки).Делая объект блокировки закрытым, он блокирует блокировку, чтобы клиентский код не мог ее получить, тогда как общедоступная блокировка позволяет клиентскому коду участвовать в его политике синхронизации - правильно или неправильно.Клиенты, которые неправильно получают блокировку другого объекта, могут вызвать проблемы жизнеспособности, и проверка правильности использования общедоступной блокировки требует проверки всей программы, а не отдельного класса.