Лично я думаю, что ответы, которые настаивают на том, что синхронизировать на this
никогда или только редко бывает неправильно, неверны. Я думаю, что это зависит от вашего API. Если ваш класс является поточно-ориентированной реализацией и вы его так документируете, то вам следует использовать this
. Если синхронизация не предназначена для того, чтобы сделать каждый экземпляр класса в целом потокобезопасным при вызове его открытых методов, то вам следует использовать закрытый внутренний объект. Многократно используемые библиотечные компоненты часто попадают в первую категорию - вы должны тщательно подумать, прежде чем запретить пользователю включать ваш API во внешнюю синхронизацию.
В первом случае использование this
позволяет вызывать несколько методов атомарным способом. Одним из примеров является PrintWriter, где вы можете захотеть вывести несколько строк (скажем, трассировку стека в консоль / регистратор) и гарантировать, что они отображаются вместе - в этом случае факт, что он скрывает объект синхронизации внутри, является реальной болью. Другим таким примером являются синхронизированные обертки коллекции - там вы должны синхронизироваться с самим объектом коллекции, чтобы выполнить итерацию; поскольку итерация состоит из нескольких вызовов методов, вы не можете полностью защитить ее.
В последнем случае я использую простой объект:
private Object mutex=new Object();
Однако, увидев много дампов JVM и трассировок стека, в которых говорится, что блокировка является «экземпляром java.lang.Object ()», я должен сказать, что использование внутреннего класса часто может быть более полезным, как предлагали другие.
В любом случае, это мои два бита.
Редактировать: Еще одна вещь, при синхронизации на this
Я предпочитаю синхронизировать методы и сохранять методы очень детальными. Я думаю, что это яснее и лаконичнее.