Помнишь ли как работать с synchronized
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
synchronized в Java
Да, я работал с synchronized и хорошо понимаю механизм monitor lock в Java.
Две формы synchronized
1. Синхронизированные методы
Блокируют весь объект (экземпляр класса):
public class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
}
2. Синхронизированные блоки
Сужают область блокировки:
public class Account {
private BigDecimal balance = BigDecimal.ZERO;
public void transfer(BigDecimal amount) {
synchronized(this) {
balance = balance.subtract(amount);
}
}
}
Как работает synchronized
Когда поток входит в synchronized блок:
- Acquisition - получить monitor lock на объект
- Wait - если другой поток имеет lock, блокируется
- Execution - выполнить критическую секцию
- Release - освободить lock при выходе
Ключевые свойства
Ре-entrant - поток может повторно блокировать:
public synchronized void method1() {
method2();
}
public synchronized void method2() {
System.out.println("OK");
}
Memory visibility - гарантирует видимость изменений благодаря memory barrier.
Основные проблемы
1. Грубая гранулярность
Весь метод становится критической секцией, даже если нужна синхронизация только в одном месте.
2. Deadlock
Account A locks this, B locks other
Account B locks other, A locks this
DEADLOCK!
Решение - всегда блокировать в одном порядке (например, по ID объекта).
3. Нет timeout
Поток будет ждать бесконечно, если lock занят.
Когда использовать synchronized
- Простые критические секции
- Не нужны timeout или interrupt
- Legacy код
Современные альтернативы
ReentrantLock из java.util.concurrent:
private final Lock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
AtomicInteger для простых операций:
private final AtomicInteger count = new AtomicInteger(0);
public void increment() {
count.incrementAndGet();
}
ConcurrentHashMap вместо synchronized HashMap.
Вывод
synchronized - мощный но грубый инструмент. Имеет риск deadlock'ов, нет timeout'ов, грубая гранулярность. В современной Java предпочитаю java.util.concurrent классы для лучшего контроля и производительности на высоконагруженных системах.