Что такое synchronized и как он работает
Что проверяют
Понимаете ли вы, что оно даёт не только взаимное исключение, но и видимость изменений.
Как отвечать
synchronized захватывает монитор объекта: одновременно в блок входит только один поток. Две формы:
synchronized void method() { } // монитор это this
static synchronized void m() { } // монитор это объект класса
synchronized (lock) { } // явный мониторДва эффекта, и второй забывают чаще:
- взаимное исключение: составная операция выполняется целиком;
- видимость: выход из блока и последующий вход образуют отношение «происходит раньше». Значит изменения, сделанные под блокировкой, гарантированно видны следующему потоку. Без этого другой поток мог бы бесконечно читать своё закэшированное значение.
Монитор реентрантный: поток, уже владеющий им, может войти повторно, счётчик увеличится.
Практические правила:
- блокируйте приватный финальный объект, а не
this. Публичныйthisможет захватить посторонний код, и вы получите взаимоблокировку, о причине которой не догадаетесь. По той же причине нельзя блокироваться на строковом литерале (он общий из пула) и на объектах из кэша обёрток; - держите секцию короткой и не вызывайте под блокировкой чужой код: он может занять монитор надолго или взять другой в обратном порядке;
- не блокируйтесь на сетевом вызове.
Альтернативы, которые стоит назвать: ReentrantLock даёт попытку захвата без ожидания (tryLock), прерываемое ожидание, честность и несколько условий; атомарные классы решают задачу счётчика без блокировок вовсе; конкурентные коллекции снимают вопрос синхронизации доступа к структуре.
Про производительность: современная виртуальная машина оптимизирует ненагруженные блокировки, поэтому synchronized дешевле, чем принято думать, и разница с ReentrantLock при низкой конкуренции невелика.
Где спотыкаются
Называют только взаимное исключение, забывая про видимость.
Синхронизируют методы по отдельности и всё равно получают гонку на составной операции.
Блокируются на this или на строке.
Считают, что synchronized нужен и для чтения неизменяемого поля.