← Назад к вопросам

Помнишь ли как работать с synchronized

2.0 Middle🔥 21 комментариев
#Docker, Kubernetes и DevOps

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

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 блок:

  1. Acquisition - получить monitor lock на объект
  2. Wait - если другой поток имеет lock, блокируется
  3. Execution - выполнить критическую секцию
  4. 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 классы для лучшего контроля и производительности на высоконагруженных системах.

Помнишь ли как работать с synchronized | PrepBro