Всякий раз, когда в SO возникает вопрос о синхронизации Java, некоторые люди очень хотят указать, чего synchronized(this)
следует избегать. Вместо этого, они утверждают, что блокировка частной ссылки должна быть предпочтительной.
Некоторые из приведенных причин:
- какой-то злой код может украсть вашу блокировку (очень популярный, также имеет «случайно» вариант)
- все синхронизированные методы в одном классе используют одинаковую блокировку, что снижает пропускную способность
- Вы (излишне) выставляете слишком много информации
Другие люди, включая меня, утверждают, что synchronized(this)
эта идиома, которая часто используется (также в библиотеках Java), безопасна и понятна. Этого не следует избегать, потому что у вас есть ошибка, и вы не знаете, что происходит в вашей многопоточной программе. Другими словами: если это применимо, то используйте его.
Я заинтересован в том, чтобы увидеть некоторые примеры из реальной жизни (без всяких вещей в foobar), где this
предпочтительнее избегать блокировки, когда synchronized(this)
это тоже можно сделать.
Поэтому: следует ли вам всегда избегать synchronized(this)
и заменять его блокировкой частной ссылки?
Некоторая дополнительная информация (обновляется по мере получения ответов):
- мы говорим о синхронизации экземпляров
- как неявные (
synchronized
методы), так и явные формыsynchronized(this)
рассматриваются - если вы цитируете Блоха или другие авторитетные источники по этому вопросу, не пропускайте части, которые вам не нравятся (например, «Эффективная Java», пункт «Потокобезопасность». Обычно это блокировка самого экземпляра, но есть исключения).
- если вам нужна гранулярность в блокировке, отличной от
synchronized(this)
предоставленной, тоsynchronized(this)
это не применимо, так что это не проблема