Ключевое слово synchronized
synchronized захватывает intrinsic monitor объекта. Пока монитор занят, другой поток не войдет в секцию, синхронизированную на том же объекте.
public synchronized void increment() {
count++;
}Эквивалентно:
public void increment() {
synchronized (this) {
count++;
}
}Статический synchronized-метод блокируется на объекте Example.class, а не на экземпляре:
public static synchronized void reset() { /* lock Example.class */ }Гарантии
- вход взаимно исключает конкурентов на том же мониторе;
- выход из блока happens-before последующего входа в блок на том же мониторе;
- монитор освобождается при обычном выходе и при исключении;
- блокировка реентерабельна.
Синхронизировать лучше минимальную секцию, сохраняющую инвариант. Медленную сеть и callbacks под монитором по возможности не выполнять: они увеличивают contention и риск deadlock.
private final Object lock = new Object();
public Snapshot snapshot() {
synchronized (lock) {
return new Snapshot(a, b);
}
}Отдельный private lock не позволяет внешнему коду случайно конкурировать на this.
На собеседовании
- На чем блокируется instance synchronized method? На
this. - На чем static synchronized? На объекте класса
Class. - Освободится ли монитор при exception? Да.
- Реентерабелен ли synchronized? Да.
- Можно ли прервать поток, ожидающий входа в synchronized? Interrupt выставит флаг, но не отменит ожидание intrinsic monitor.