На каких объектах не следует синхронизироваться?
Не синхронизироваться на разделяемых или подменяемых объектах: строковых литералах (интернированы), Integer и других обёртках (кэш значений), публичном this, изменяемом поле. Правильно — private final Object lock.
- Посторонний код может случайно взять тот же монитор — загадочный deadlock
- Переприсвоенное поле — потоки синхронизируются на разных объектах
- Value-based классы (Integer, Optional, LocalDate) — предупреждение компилятора
А ещё Монитор на виртуальных потоках до JDK 24 вызывал pinning
Подробно
Опасность в том, что монитор может оказаться общим с совершенно посторонним кодом: строковые литералы интернируются в один экземпляр, а Integer.valueOf возвращает объект из кэша для малых значений — в результате два независимых участка кода блокируют друг друга, и появляется загадочный deadlock. Синхронизация на this проблематична, когда объект публичен: внешний код может захватить тот же монитор и удерживать его сколь угодно долго. Отдельная классическая ошибка — синхронизироваться на изменяемом поле: если ссылку переприсвоить, потоки будут блокировать разные объекты, и защиты не будет вовсе. Отсюда идиома: private final Object lock = new Object() и блокировка на нём.
Что хотят услышать
- Опасные варианты и причины.
- Приватный final-объект.
Частые ошибки
- Синхронизироваться на поле, которое может быть переприсвоено.
- Считать synchronized на публичном методе безопасным по умолчанию.
Проверьте себя
Несколько верных вариантов. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✓На строковых литералах: они интернированы и общие с чужим кодом
- ✗На приватном final Object, созданном специально для блокировки, — его монитор доступен любому коду через рефлексию
- ✓На обёртках вроде Integer: из-за кэша монитор может быть общим
- ✓На публично доступном this: внешний код захватит ваш монитор
Что спросят дальше
- Почему синхронизация на изменяемом поле не работает?
- Чем блокировка на приватном объекте лучше synchronized-метода?
Разбор темы
- synchronized, мониторы и wait/notify
Взаимное исключение и видимость через монитор, reentrancy, guarded blocks с wait/notify и причины deadlock.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.